【问题标题】:Excluding files and folders during plugin publishing在插件发布期间排除文件和文件夹
【发布时间】:2025-12-18 19:40:01
【问题描述】:

当我将插件发布到我们的自定义 Artifactory 存储库时,我想排除 .svn 文件夹。我假设包含 .svn 文件夹是基于下面提供的错误跟踪跟踪的问题。

我正在使用以下命令发布:

gradlew artifactoryPublish --stacktrace

这是build.gradle中的发布块:

artifactory {
    contextUrl = artifactory_context
    publish {
        repository {
            repoKey = 'plugins-release-local'
            username = artifactory_user
            password = artifactory_password
            maven = true

        }
        defaults {
            publications ('mavenJava')
        }
    }
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
        }
    }
}

这是我尝试发布时得到的堆栈跟踪,注意.svn/entriesassets/entries 的尝试副本。

...
:copyAssets FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':copyAssets'.
> Could not copy file '/u01/var/build/pluginXYZ/grails-app/assets/.svn/entries' to '/u01/var/build/pluginXYZ/build/resources/main/META-INF/assets/entries'.

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':copyAssets'.
...
Caused by: org.gradle.api.GradleException: Could not copy file '/u01/var/build/pluginXYZ/grails-app/assets/.svn/entries' to '/u01/var/build/pluginXYZ/build/resources/main/META-INF/assets/entries'.
...
Caused by: java.io.FileNotFoundException: /u01/var/build/pluginXYZ/build/resources/main/META-INF/assets/entries (Permission denied)
... 80 more

entries(两棵树)的权限是-r--r--r--

如果我排除这些文件夹,我应该摆脱上述权限问题。第一次结帐总是会发布,但随后的发布(比如在更新之后)会因此错误而失败。

更新 #2

以下是我尝试过的三种组合,但均未成功:

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
                //first attempt
                //exclude("**/.svn/**")
                //second attempt
                //exclude{ details -> details.file.name.contains(".svn") }
                //third attempt
                //exclude "**/.svn/**"
        }
    }
}

使用所有三种尝试发布时的错误输出如下:

Caused by: org.gradle.api.internal.MissingMethodException: Could not find method exclude() for arguments [build_3nsvrqvwahy23ir3fxdj970id$_run_closure7_closure13_closure14_closure15@10e9a5fe] on org.gradlpublish.maven.internal.publication.DefaultMavenPublication_Decorated@ca7e37f.

更新 #3

我找到了以下链接taking about excluding files

然后我将我的gradle.build 调整为:

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java {
                        exclude "**/.svn/**"
                }
        }
    }
}

同样的错误。

更新 #4

更多尝试...相同的结果

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
            artifact sourceJar{
                exclude '**/.svn/**'
            } 
        }
    }
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
            artifact  exclude '**/.svn/**'
        }
    }
}

【问题讨论】:

    标签: gradle build.gradle gradlew


    【解决方案1】:

    假设您有一个文件,您希望在发布到存储库时避免该文件。如果你按照@TekiusFanatikus 的建议去

    sourceSets {
      main {
        java {
          exclude '**/.svn/**'
        }
      }
    }
    

    您将能够实现它,但这也会从您使用 gradle build 生成的工件中排除文件/文件夹等。

    相反,我建议使用这里提到的方法gradle documnetation

    您可以创建一个应用了所需排除的任务

    task apiJar(type: Jar) {
        baseName "publishing-api"
        from sourceSets.main.output
        exclude '**/.svn/**'
    }
    

    然后在发布时参考任务。

    publishing {
        publications {
            api(MavenPublication) {
                groupId 'org.gradle.sample'
                artifactId 'project2-api'
                version '2'
    
                artifact apiJar
            }
        }
    }
    

    这样,被发布的 jar 将没有 .svn 文件夹。我想在这里说明的一点是,它不会触及您使用 gradle build 创建的工件。它仍然会有你的 .svn 文件夹。

    但是,如果您希望将其从这两个地方都删除,那么最好的选择就是上面的建议。

    【讨论】:

      【解决方案2】:

      我想扩展@Neeraj 的答案。自定义 JAR 方法的问题在于它不能生​​成有效的 POM——尤其是在多模块项目的情况下——这与正确生成 POM 的from components.java 方法不同。

      为了克服这个问题,我们可以声明两个发布 - 一个内部仅用于生成 POM,第二个是我们希望发布的实际发布(没有排除的文件):

      task apiJar(type: Jar) {
          baseName "publishing-api"
          from sourceSets.main.output
          exclude '**/.svn/**'
      }
      
      publishing {
          publications {
              def pomString = null
      
              internal(MavenPublication) {
                  from components.java
                  pom.withXml {
                      pomString = asString().toString()
                  }
              }
      
              api(MavenPublication) {
                  artifact apiJar
                  pom.withXml {
                      def builder = asString()
                      builder.delete(0, builder.length())
                      builder.append(pomString)
                  }
              }
          }
      }
      
      generatePomFileForApiPublication.dependsOn(generatePomFileForInternalPublication)
      
      artifactoryPublish {
          publications('api')
      }
      

      注意generatePomFileForXPublication任务的名称是根据发布的名称来确定的。


      旧答案

      这是我之前手动生成 POM 的尝试,但它不如上面的新答案那么完整。

      task apiJar(type: Jar) {
          baseName "publishing-api"
          from sourceSets.main.output
          exclude '**/.svn/**'
      }
      
      publishing {
          publications {
              api(MavenPublication) {
                  artifact apiJar
      
                  pom.withXml {
                      def dependenciesNode = asNode().appendNode("dependencies")
                      project.configurations.runtimeClasspath.resolvedConfiguration.firstLevelModuleDependencies.forEach { d ->
                          def dependencyNode = dependenciesNode.appendNode("dependency")
                          dependencyNode.appendNode("groupId", d.moduleGroup)
                          dependencyNode.appendNode("artifactId", d.moduleName)
                          dependencyNode.appendNode("version", d.moduleVersion)
                      }
                  }
              }
          }
      }
      
      artifactoryPublish {
          publications('api')
      }
      

      【讨论】:

        【解决方案3】:

        我认为您可以在文件过滤器中使用“排除”方法。只需将其添加到发布块中的“发件人”下即可。

        【讨论】:

        • 我尝试了 3 种不同的配置(请参阅更新 2),但均未成功。不确定我是否实现了您的想法。
        • 看起来您的 components.java 错误尝试像工件文件(“path-to-jar/jar.jar”)一样明确指定工件。
        • 你不可能为我编写一些伪代码吗?到目前为止,任何使用 exclude 附加工件的尝试都会引发相同的错误。
        【解决方案4】:

        我在build.gradle 的根级别附加了以下内容,它似乎有效:

        sourceSets {
          main {
            java {
              exclude '**/.svn/**'
            }
          }
        }
        

        【讨论】: