89

现在 maven-3 确实放弃了对快照工件的 <uniqueVersion>false</uniqueVersion> 的支持,看来您确实需要使用带时间戳的 SNAPSHOTS。特别是在内部使用 maven 3 的 m2eclipse 似乎受到了影响,当 SNAPSHOTS 不唯一时,更新快照不起作用。

将所有快照设置为 uniqueVersion=false之前似乎是最佳实践

现在,切换到时间戳版本似乎没有什么大问题,毕竟它们是由一个中央关系存储库管理的,它能够定期删除旧快照。

问题在于本地开发人员工作站。他们的本地存储库很快就会通过独特的快照变得非常大。

如何处理这个问题?

现在我看到以下可能的解决方案:

  • 要求开发人员定期清除存储库(这会导致很多麻烦,因为删除需要很长时间,下载所需的一切需要更长的时间)
  • 设置一些脚本,从本地存储库中删除所有SNAPSHOT目录,并要求开发人员不时运行该脚本(比第一个更好,但仍然需要相当长的时间来运行和下载当前快照)
  • 使用依赖:purge-local-repository 插件(从eclipse运行时确实有问题,由于打开文件,需要从每个项目运行)
  • 在每个工作站上设置 nexus 并设置清理旧快照的作业(最好的结果,但我不想维护 50 多个 nexus 服务器,而且开发人员工作站上的内存总是很紧张)
  • 完全停止使用 SNAPSHOTS

防止本地存储库填满硬盘空间的最佳方法是什么?

更新:

为了验证行为并提供更多信息,我设置了一个小型 nexus 服务器,构建两个项目(a 和 b)并尝试:

A:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>de.glauche</groupId>
  <artifactId>a</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <distributionManagement>
    <snapshotRepository>
        <id>nexus</id>
        <name>nexus</name>
        <url>http://server:8081/nexus/content/repositories/snapshots</url>
    </snapshotRepository>
  </distributionManagement>

</project>

乙:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>de.glauche</groupId>
  <artifactId>b</artifactId>
  <version>0.0.1-SNAPSHOT</version>
    <distributionManagement>
    <snapshotRepository>
        <id>nexus</id>
        <name>nexus</name>
        <url>http://server:8081/nexus/content/repositories/snapshots/</url>
    </snapshotRepository>
  </distributionManagement>
 <repositories>
    <repository>
        <id>nexus</id>
        <name>nexus</name>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
        <url>http://server:8081/nexus/content/repositories/snapshots/</url>
    </repository>
 </repositories>
  <dependencies>
    <dependency>
        <groupId>de.glauche</groupId>
        <artifactId>a</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
  </dependencies>
</project>

现在,当我使用 Maven 并在“a”上运行“deploy”时,我将拥有

a-0.0.1-SNAPSHOT.jar
a-0.0.1-20101204.150527-6.jar
a-0.0.1-SNAPSHOT.pom
a-0.0.1-20101204.150527-6.pom

在本地存储库中。每次运行部署目标时都会使用新的时间戳版本。当我尝试从 nexus 服务器更新快照时也会发生同样的情况(关闭“a”项目,从本地存储库中删除它,构建“b”)

在构建大量快照的环境中(想想哈德逊服务器......),本地存储库很快就会被旧版本填满

更新 2:

为了测试失败的方式和原因,我做了更多的测试。每个测试都针对干净的所有内容运行(de/glauche 从机器和连接中删除)

  • mvn 使用 Maven 2.2.1 部署:

机器 A 上的本地存储库确实包含 snapshot.jar + snapshot-timestamp.jar

但是:nexus 中只有一个带时间戳的 jar,元数据读取:

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
  <groupId>de.glauche</groupId>
  <artifactId>a</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <versioning>
    <snapshot>
      <timestamp>20101206.200039</timestamp>

      <buildNumber>1</buildNumber>
    </snapshot>
    <lastUpdated>20101206200039</lastUpdated>
  </versioning>
</metadata>
  • 在 m2eclipse(嵌入式 m3 final)中运行更新依赖项(在机器 B 上)-> 本地存储库有 snapshot.jar + snapshot-timestamp.jar :(
  • 使用外部 maven 2.2.1 运行包目标 -> 本地存储库具有 snapshot.jar + snapshot-timestamp.jar :(

好的,接下来尝试使用 maven 3.0.1(删除项目 a 的所有痕迹后)

  • 机器 A 上的本地存储库看起来更好,只有一个非时间戳 jar

  • 在 nexus 中只有一个带时间戳的 jar,元数据读取:

    de.glauche a 0.0.1-SNAPSHOT

    <snapshot>
      <timestamp>20101206.201808</timestamp>
      <buildNumber>3</buildNumber>
    </snapshot>
    <lastUpdated>20101206201808</lastUpdated>
    <snapshotVersions>
      <snapshotVersion>
        <extension>jar</extension>
        <value>0.0.1-20101206.201808-3</value>
        <updated>20101206201808</updated>
      </snapshotVersion>
      <snapshotVersion>
        <extension>pom</extension>
        <value>0.0.1-20101206.201808-3</value>
        <updated>20101206201808</updated>
      </snapshotVersion>
    </snapshotVersions>
    

  • 在 m2eclipse(嵌入式 m3 final)中运行更新依赖项(在机器 B 上)-> 本地存储库有 snapshot.jar + snapshot-timestamp.jar :(

  • 使用外部 maven 2.2.1 运行包目标 -> 本地存储库具有 snapshot.jar + snapshot-timestamp.jar :(

因此,回顾一下:maven3 中的“部署”目标比 2.2.1 中的效果更好,创建机器上的本地存储库看起来不错。但是,接收器总是以许多带有时间戳的版本结束......

我究竟做错了什么 ?

更新 3

我还测试了其他各种配置,首先用人工制品替换 nexus -> 相同的行为。然后使用 linux maven 3 客户端从存储库管理器下载快照 -> 本地存储库仍然有时间戳快照 :(

4

6 回答 6

37

<uniqueVersion>应用于已部署(通过 mvn deploy)到 Maven 存储库(例如 Nexus)的工件 的配置。

要从 Nexus 中删除这些,您可以轻松地创建一个自动化作业来每天清除 SNAPSHOT 存储库。它可以配置为保留一定数量的快照或将它们保留一段时间。它超级简单,效果很好。

开发人员机器上本地存储库中的工件从“安装”目标到达那里,并且不使用这些时间戳......它们只是不断替换唯一的 SNAPSHOT 版本,除非您还增加修订号(例如 1.0.0-快照到 1.0.1-快照)。

于 2010-12-01T18:36:25.853 回答
15

此插件从本地存储库中删除项目的工件。仅保留一份大型本地快照的副本很有用。

<plugin>         
    <groupId>org.codehaus.mojo</groupId>         
    <artifactId>build-helper-maven-plugin</artifactId>         
    <version>1.7</version>         
    <executions>           
        <execution>             
            <id>remove-old-artifacts</id>             
            <phase>package</phase>             
            <goals>               
                <goal>remove-project-artifact</goal>             
            </goals>            
            <configuration>  
                <removeAll>true</removeAll><!-- When true, remove all built artifacts including all versions. When false, remove all built artifacts of this project version -->             
            </configuration>          
        </execution>         
    </executions>       
</plugin>
于 2011-09-06T13:34:46.460 回答
9

好吧,我不喜欢任何建议的解决方案。删除 Maven 缓存通常会显着增加网络流量并减慢构建过程。build-helper-maven-plugin 仅对一个工件有帮助,我想要一个可以通过一个简单的命令从本地缓存中清除所有过时的时间戳快照工件的解决方案。经过几天的搜索,我放弃了,决定写一个小程序。最终程序似乎在我们的环境中运行良好。因此,我决定与可能需要此类工具的其他人分享。可以从 github 拉取源代码:https ://github.com/nadestin/tools/tree/master/MavenCacheCleanup

于 2013-07-08T07:02:54.363 回答
2

就远程存储库而言,我认为先前讨论定期清除 SNAPSHOT 的答案将起作用。但是没有人解决您问题的本地开发人员工作站同步部分。

我们还没有开始使用 Maven3,所以我们还没有看到 SNAPSHOT 开始在本地机器上构建。

但是我们对 m2eclipse 有不同的问题。当我们启用“工作空间分辨率”并且项目存在于我们的工作空间中时,源更新通常使我们处于最前沿。但是我们发现要让 m2eclipse 用最近在 Nexus 中发布的工件来更新自己是非常困难的。我们在我们的团队中遇到了类似的问题,这尤其成问题,因为我们有一个非常大的项目图......有很多依赖项不会出现在您的工作区中,但会经常发布 SNAPSHOT。

我很确定这可以归结为 m2eclipse 中的一个问题,它不能完全按照应有的方式处理 SNAPSHOT。您可以在 Eclipse 中的 Maven 控制台中看到 m2eclipse 告诉您它正在跳过最近发布的 SNAPSHOT 的更新,因为它有一个缓存版本。如果您从运行配置或命令行执行 -U,Maven将获取元数据更改。但是“更新快照...”选项应该告诉 m2eclipse 让 Maven 使这个缓存过期。它似乎没有被传递。如果您有兴趣投票,似乎有一个错误已提交: https ://issues.sonatype.org/browse/MNGECLIPSE-2608

您在某处的评论中提到了这一点。

这个问题的最佳解决方法似乎是让开发人员在 m2eclipse 内部出现问题时清除他们的本地工作站。不同问题的类似解决方案......其他人报告了支持 m2eclipse 的 Maven 2.2.1 和 3 的问题,我也看到了同样的情况。

我希望如果您使用的是 Maven3,您可以将其配置为仅提取最新的 SNAPSHOT,并将其缓存到存储库所说的时间(或直到您手动将其过期)。希望那时您不需要在本地存储库中放置一堆 SNAPSHOT。

除非您谈论的是手动执行的构建服务器mvn install在他们。至于如何防止 SNAPSHOT 在构建服务器之类的环境中构建,我们通过让每个构建使用自己的工作区和本地存储库(尽管在 Maven 2.2.1 中,某些东西,例如POM 似乎总是来自 ~/.m2/repository) 额外的 SNAPSHOT 真的只存在于单个构建中,然后它们被丢弃(并从头开始重新下载)。所以我们已经看到,这种方法一开始确实会占用更多空间,但它往往比将所有内容都从单个存储库中解析出来更稳定。此选项(在 Hudson 上)称为“使用私有 Maven 存储库”,当您选择使用 Maven 构建时,它位于项目配置的构建部分的高级按钮下。以下是该选项的帮助说明:

通常,Hudson 使用由 Maven 确定的本地 Maven 存储库——确切的过程似乎没有记录,但它是 ~/.m2/repository 并且可以在 ~/.m2/settings.xml 中被覆盖(有关更多详细信息,请参阅参考资料.) 这通常意味着在同一节点上执行的所有作业共享一个 Maven 存储库。这样做的好处是可以节省磁盘空间,但缺点是有时这些构建可能会相互干扰。例如,您可能最终导致构建错误地成功,只是因为您在本地存储库中拥有所有依赖项,尽管事实上 POM 中的任何存储库都没有它们。

还有一些关于让并发 Maven 进程尝试使用相同的本地存储库的问题。

选中此选项后,Hudson 将告诉 Maven 使用 $WORKSPACE/.repository 作为本地 Maven 存储库。这意味着每个作业都将获得自己独立的 Maven 存储库。它解决了上述问题,但会消耗额外的磁盘空间。

使用此选项时,请考虑设置一个 Maven 工件管理器,这样您就不必经常访问远程 Maven 存储库。

如果您希望在 Hudson 上执行的所有 Maven 作业中激活此模式,请参阅此处描述的技术。

希望这会有所帮助 - 如果它不能解决您的问题,请让我知道我错过了哪里。

于 2011-01-18T23:11:47.660 回答
1

在 groovy中,删除带时间戳的文件artifact-0.0.1-20101204.150527-6.jar可能非常简单:

root = 'path to your repository'

new File(root).eachFileRecurse {
  if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
    println 'Deleting ' + it.name
    it.delete()
  }
}

安装Groovy,将脚本保存到文件中,并安排每周执行、启动、登录等任何适合您的操作。

或者,您甚至可以使用gmavenplus-plugin将执行连接到 maven 构建中。注意,存储库位置是如何由 maven 设置到属性中settings.localRepository,然后通过配置绑定到变量中的repository

  <plugin>
    <groupId>org.codehaus.gmavenplus</groupId>
    <artifactId>gmavenplus-plugin</artifactId>
    <version>1.3</version>
    <executions>
      <execution>
        <phase>install</phase>
        <goals>
          <goal>execute</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <properties>
        <property>
          <name>repository</name>
          <value>${settings.localRepository}</value>
        </property>
      </properties>
      <scripts>
        <script><![CDATA[
          new File(repository).eachFileRecurse {
            if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
              println 'Deleting snapshot ' + it.getAbsolutePath()
              it.delete()
            }
          }
        ]]></script>
      </scripts>
    </configuration>
    <dependencies>
      <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.3.7</version>
        <scope>runtime</scope>
      </dependency>
    </dependencies>
  </plugin>  
于 2015-01-23T12:13:05.923 回答
0

将以下参数添加到您的 POM 文件中

聚甲醛

<configuration>
<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>
</configuration>

https://maven.apache.org/plugins/maven-dependency-plugin/copy-mojo.html

POM 示例

<plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.10</version>
        <executions>
          <execution>
            <id>copy</id>
            <phase>package</phase>
            <goals>
              <goal>copy</goal>
            </goals>
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>junit</groupId>
                  <artifactId>junit</artifactId>
                  <version>3.8.1</version>
                  <type>jar</type>
                  <overWrite>false</overWrite>
                  <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
                  <destFileName>optional-new-name.jar</destFileName>
                </artifactItem>
              </artifactItems>
              **<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>**
              <outputDirectory>${project.build.directory}/wars</outputDirectory>
              <overWriteReleases>false</overWriteReleases>
              <overWriteSnapshots>true</overWriteSnapshots>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

在 Jenkins 中配置:

// copy artifact 
copyMavenArtifact(artifact: "commons-collections:commons-collections:3.2.2:jar", outputAbsoluteArtifactFilename: "${pwd()}/target/my-folder/commons-collections.jar")
于 2016-07-26T21:28:25.013 回答