你如何有效地处理maven-3时间戳快照?

时间:2010-11-25 09:25:44

标签: java maven-3

现在maven-3为< uniqueVersion> false< / uniqueVersion>做了drop support对于快照伪像,您似乎确实需要使用带时间戳的SNAPSHOTS。特别是在内部使用maven 3的m2eclipse似乎受其影响,当SNAPSHOTS不是唯一时,更新快照不起作用。

将所有快照设置为uniqueVersion = false

似乎最好practice before

现在,切换到带时间戳的版本似乎没什么大不了的,毕竟它们是由中央nexus存储库管理的,它可以在常规的intervalls中删除旧的快照。

问题是本地开发人员工作站。他们的本地存储库很快就可以通过独特的快照实现非常大。

如何处理这个问题?

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

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

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

更新

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

一个:

<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>

B:

<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”)

在构建大量快照的环境中(想想哈德森服务器......),本地reposioty填充旧版本快速

更新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中运行更新依赖项(在机器B上)(嵌入式m3 final) - &gt;本地存储库有snapshot.jar + snapshot-timestamp.jar :(
  • 使用外部maven 2.2.1运行包目标 - &gt;本地存储库有snapshot.jar + snapshot-timestamp.jar :(

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

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

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

      de.glauche   一个   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中运行更新依赖项(在机器B上)(嵌入式m3 final) - &gt;本地存储库有snapshot.jar + snapshot-timestamp.jar :(

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

因此,回顾一下:maven3中的“部署”目标比2.2.1更好,创建机器上的本地存储库看起来很好。 但是,接收器总是有很多时间限制的版本......

我做错了什么?

更新3

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

6 个答案:

答案 0 :(得分:34)

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

要从Nexus中删除这些内容,您可以轻松创建自动作业,以便每天清除SNAPSHOT存储库。它可以配置为保留一定数量的shapshots或保持一段时间。它超级简单,效果很好。

开发人员计算机上的本地存储库中的工件从“安装”目标到达那里并且不使用这些时间戳...他们只是继续替换一个且只有SNAPSHOT版本,除非您也在增加修订号(例如1.0) .0-SNAPSHOT到1.0.1-SNAPSHOT)。

答案 1 :(得分:13)

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

<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>

答案 2 :(得分:7)

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

答案 3 :(得分:2)

就远程存储库而言,我认为之前讨论定期清除SNAPSHOTs的答案是有效的。但是没有人解决你问题的本地开发者工作站同步部分。

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

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

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

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

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

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

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

  

通常,Hudson使用本地Maven   由Maven确定的存储库 -   确切的过程似乎是   没有证件,但它是   〜/ .m2 / repository并且可以被覆盖   在...   〜/ .m2 / settings.xml(参见参考资料)   更多细节。)这通常意味着   所有执行的作业   同一节点共享一个Maven   库。这样做的好处就是   你可以保存磁盘空间,但是   这种情况的缺点是有时候   这些构建可能会干扰每个   其他。例如,您最终可能会结束   生成错误成功,   只因为你拥有所有   本地存储库中的依赖项,   尽管没有这个事实   POM中的存储库可能有它们。

     

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

     

选中此选项后,Hudson   会告诉Maven使用   $ WORKSPACE / .repository作为本地   Maven存储库。这意味着每项工作   将获得自己的孤立Maven   存储库只为自己。它修复了   以上问题,以牺牲为代价   额外的磁盘空间消耗。

     

使用此选项时,请考虑   设置一个Maven工件经理   你不必打远程   Maven存储库太频繁了。

     

如果您更喜欢激活此模式   在执行的所有Maven工作中   哈德森,参考技术   这里描述。

希望这会有所帮助 - 如果它没有解决您的问题,请告诉我错过的地方。

答案 4 :(得分: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>  

答案 5 :(得分:0)

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

<强> 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")