Java 你如何有效地处理 maven-3 时间戳快照?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4275466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you deal with maven-3 timestamped snapshots efficiently?
提问by mglauche
Now that maven-3 did drop supportfor the <uniqueVersion>false</uniqueVersion> for snapshot artefacts it seems that you really need to use timestamped SNAPSHOTS. Especially m2eclipse, which does use maven 3 internally seems to be affected with it, update-snapshots does not work when the SNAPSHOTS are not unique.
既然 maven-3 确实放弃了对 <uniqueVersion>false</uniqueVersion> 快照人工制品的支持,看来您确实需要使用带时间戳的 SNAPSHOTS。特别是 m2eclipse,它在内部确实使用了 maven 3 似乎受到了它的影响,当 SNAPSHOTS 不是唯一的时,更新快照不起作用。
It seemed best practice beforeto set all snapshots to uniqueVersion=false
将所有快照设置为 uniqueVersion=false之前似乎是最佳实践
Now, it seems no big problem to switch to the timestamped version, after all they are managed by a central nexus repository, which is able to delete old snapshots in regular intervalls.
现在,切换到带时间戳的版本似乎没什么大问题,毕竟它们是由中央 nexus 存储库管理的,该存储库能够定期删除旧快照。
The problem are the local developer workstations. Their local repository quickly does grow verylarge with unique snapshots.
问题在于本地开发人员工作站。他们的本地存储库确实随着独特的快照迅速增长得非常大。
How to deal with this problem ?
如何处理这个问题?
Right now i see the folowing possible solutions:
现在我看到以下可能的解决方案:
- Ask the developers to purge the repository in regular intervals (which leads to lots of fustration, as it takes long time to delete and even longer to download everything needed)
- Set up some script which does delete all SNAPSHOTdirectories from the local repository and ask developers to run that script from time to time (better than the first, but still takes quite some time to run and download current snapshots)
- use the dependency:purge-local-repository plugin (Does have problems when run from eclipse, due to open files, needs to be run from each project)
- set up nexus on every workstation and set up a job to clean old snapshots (best result, but I don't want to maintain 50+ nexus servers, plus memory is always tight on developer workstations)
- stop using SNAPSHOTS at all
- 要求开发人员定期清除存储库(这会导致很多麻烦,因为删除需要很长时间,下载所需的所有内容甚至需要更长时间)
- 设置一些脚本,从本地存储库中删除所有SNAPSHOT目录,并要求开发人员不时运行该脚本(比第一个好,但仍然需要相当长的时间来运行和下载当前快照)
- 使用依赖项:purge-local-repository 插件(从eclipse运行时确实有问题,由于打开的文件,需要从每个项目运行)
- 在每个工作站上设置 nexus 并设置清理旧快照的作业(最佳结果,但我不想维护 50 多个 nexus 服务器,而且开发人员工作站的内存总是很紧)
- 完全停止使用快照
What is the best way to keep your local repository from filling up your hard drive space ?
防止本地存储库填满硬盘空间的最佳方法是什么?
Update:
更新:
To verify the beaviour and to give more info i setup a small nexus server, build two projects (a and b) and try:
为了验证行为并提供更多信息,我设置了一个小型 nexus 服务器,构建两个项目(a 和 b)并尝试:
a:
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>
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>
Now, when i use maven and run "deploy" on "a", i'll have
现在,当我使用 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
in the local repository. With a new timestamp version each time i run the deploy target. The same happens when i try to update Snapshots from the nexus server (close "a" Project, delete it from local repository, build "b")
在本地存储库中。每次运行部署目标时都有一个新的时间戳版本。当我尝试从 nexus 服务器更新快照时也会发生同样的情况(关闭“a”项目,从本地存储库中删除它,构建“b”)
In an environment where lots of snapshots get build (think hudson server ...), the local reposioty fills up with old versions fast
在构建大量快照的环境中(想想 hudson 服务器...),本地存储库会快速填满旧版本
Update 2:
更新 2:
To test how and why this is failing i did some more tests. Each test is run against clean everything (de/glauche gets delete from both machines and nexus)
为了测试失败的方式和原因,我做了更多的测试。每个测试都针对干净的所有内容运行(de/glauche 从机器和 nexus 中删除)
- mvn deploy with maven 2.2.1 :
- mvn 使用 maven 2.2.1 部署:
local repository on machine A does contain snapshot.jar + snapshot-timestamp.jar
机器 A 上的本地存储库确实包含 snapshot.jar + snapshot-timestamp.jar
BUT: only one timestamped jar in nexus, metadata reads:
但是: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>
- run update dependencies (on machine B) in m2eclipse (embedded m3 final) -> local repository has snapshot.jar + snapshot-timestamp.jar :(
- run package goal with external maven 2.2.1 -> local repository has snapshot.jar + snapshot-timestamp.jar :(
- 在 m2eclipse(嵌入式 m3 final)中运行更新依赖项(在机器 B 上)-> 本地存储库具有 snapshot.jar + snapshot-timestamp.jar :(
- 使用外部 maven 2.2.1 运行包目标 -> 本地存储库具有 snapshot.jar + snapshot-timestamp.jar :(
Ok, next try with maven 3.0.1 (after removing all traces of project a)
好的,接下来尝试使用 maven 3.0.1(删除项目 a 的所有痕迹后)
local repository on machine A looks better, only one one non-timestamped jar
only one timestamped jar in nexus, metadata reads:
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>
run update dependencies (on machine B) in m2eclipse (embedded m3 final) -> local repository has snapshot.jar + snapshot-timestamp.jar :(
run package goal with external maven 2.2.1 -> local repository has snapshot.jar + snapshot-timestamp.jar :(
机器 A 上的本地存储库看起来更好,只有一个没有时间戳的 jar
nexus 中只有一个带时间戳的 jar,元数据显示:
de.glache 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 :(
So, to recap: The "deploy" goal in maven3 works better than in 2.2.1, the local repository on the creating machine looks fine. But, the receiver always ends up with lots of timestamed versions ...
因此,总结一下:maven3 中的“部署”目标比 2.2.1 中的效果更好,创建机器上的本地存储库看起来不错。但是,接收器总是以很多时间标记的版本结束......
What am i doing wrong ?
我究竟做错了什么 ?
Update 3
更新 3
I also did test various other configurations, first replace nexus with artifactory -> same behaviour. Then use linux maven 3 clients to download the snapshots from the repository manager -> local repository still has timestamped snapshots :(
我还测试了各种其他配置,首先用 artifactory 替换 nexus -> 相同的行为。然后使用 linux maven 3 客户端从存储库管理器下载快照 -> 本地存储库仍然有带时间戳的快照:(
采纳答案by HDave
The <uniqueVersion>
configuration applied to artifacts that were deployed (via mvn deploy) to a Maven repository such as Nexus.
<uniqueVersion>
应用于已部署(通过 mvn deploy)到 Maven 存储库(例如 Nexus)的工件的配置。
To remove these from Nexus, you can easily create an automated job to purge the SNAPSHOT repository every day. It can be configured to retain a certain number of shapshots or keep them for a certain period of time. Its super easy and works great.
要将这些从 Nexus 中删除,您可以轻松地创建一个自动化作业来每天清除 SNAPSHOT 存储库。它可以配置为保留一定数量的快照或将它们保留一段时间。它超级简单,效果很好。
Artifacts in the local repository on a developer machine get there from the "install" goal and do not use these timestamps...they just keep replacing the one and only SNAPSHOT version unless you are also incrementing the revision number (e.g. 1.0.0-SNAPSHOT to 1.0.1-SNAPSHOT).
开发人员机器上本地存储库中的工件从“安装”目标到达那里,并且不使用这些时间戳……它们只是不断替换一个且唯一的 SNAPSHOT 版本,除非您还增加了修订号(例如 1.0.0-快照到 1.0.1-快照)。
回答by cwash
As far as the remote repository piece of this, I think the previous answers that discuss a purging of SNAPSHOTs on a regular interval will work. But no one has addressed the local-developer workstation synchronization part of your question.
就远程存储库而言,我认为之前讨论定期清除快照的答案会起作用。但是没有人解决您问题的本地开发人员工作站同步部分。
We have not started using Maven3 yet, so we've yet to see SNAPSHOTs starting to build up on local machines.
我们还没有开始使用 Maven3,所以我们还没有看到 SNAPSHOT 开始在本地机器上构建。
But we have had different problems with m2eclipse. When we have "Workspace Resolution" enabled and the project exists within our workspace, source updates usually keep us on the bleeding edge. But we've found it's very difficult to get m2eclipse to update itself with recently published artifacts in Nexus. We're experiencing similar problems within our team and it's particularly problematic because we have a very large project graph... there are a lot of dependencies that won't be in your workspace but will be getting SNAPSHOTs published frequently.
但是我们在使用 m2eclipse 时遇到了不同的问题。当我们启用“工作区分辨率”并且项目存在于我们的工作区中时,源代码更新通常会让我们处于最前沿。但是我们发现很难让 m2eclipse 使用 Nexus 中最近发布的工件来更新自己。我们在我们的团队中遇到了类似的问题,这尤其成问题,因为我们有一个非常大的项目图……有很多依赖项不会在您的工作区中,但会经常发布 SNAPSHOT。
I'm pretty sure this boils back to an issue in m2eclipse where it doesn't handle SNAPSHOTs exactly as it should. You can see in the Maven console within eclipse where m2eclipse tells you it's skipping the update of a recently published SNAPSHOT because it's got a cached version. If you do a -U from a run configuration or from the command line, Mavenwill pick up the metadata change. But an "Update Snapshots..." selection should tell m2eclipse to have Maven expire this cache. It doesn't appear to be getting passed along. There appears to be a bug out there that is filed for this if you're interested in voting for it: https://issues.sonatype.org/browse/MNGECLIPSE-2608
我很确定这归结为 m2eclipse 中的一个问题,它没有完全按照它应该的方式处理快照。您可以在 Eclipse 的 Maven 控制台中看到 m2eclipse 告诉您它正在跳过最近发布的 SNAPSHOT 的更新,因为它有一个缓存版本。如果您从运行配置或命令行执行 -U,Maven将获取元数据更改。但是“更新快照...”选择应该告诉 m2eclipse 让 Maven 使这个缓存过期。它似乎没有被传递。如果您有兴趣为其投票,似乎有一个错误已提交:https: //issues.sonatype.org/browse/MNGECLIPSE-2608
You made mention of this in a comment somewhere.
您在某处的评论中提到了这一点。
The best workaround for this problem seems to be having developers purge their local workstations when things start to break down from within m2eclipse. Similar solution to a different problem... Others have reported problems with Maven 2.2.1 and 3 backing m2eclipse, and I've seen the same.
这个问题的最佳解决方法似乎是让开发人员在 m2eclipse 内部开始出现故障时清除他们的本地工作站。不同问题的类似解决方案......其他人报告了 Maven 2.2.1 和 3 支持 m2eclipse 的问题,我也看到了同样的问题。
I would hope if you're using Maven3 you can configure it to only pull the latest SNAPSHOT, and cache that for the amount of time the repository says (or until you expire it by hand). Hopefully then you won't need to have a bunch of SNAPSHOTs sitting in your local repository.
我希望如果您使用 Maven3,您可以将其配置为仅提取最新的 SNAPSHOT,并将其缓存到存储库所说的时间(或直到您手动将其过期)。希望您不需要在本地存储库中放置一堆快照。
That is unless you're talking about a build server that is manually doing a mvn install
on them. As far as how to prevent SNAPSHOTs from building up on an environment like a build server, we've kind of dodged that bullet by having each build use its own workspace and local repository (though, in Maven 2.2.1, certain things such as POMs seem to always come out of the ~/.m2/repository) The extra SNAPSHOTs really only stick around for a single build and then they get dropped (and downloaded again from scratch). So we've seen this approach does end up eating up more space to begin with, but it tends to remain more stable than having everything resolved out of a single repository. This option (on Hudson) is called "Use private Maven repository" and is under the Advanced button of the Build section on project configurations when you've selected to build with Maven. Here is the help description for that option:
除非您谈论的是手动执行的构建服务器 mvn install
在他们。至于如何防止 SNAPSHOT 在构建服务器等环境中构建,我们通过让每个构建使用自己的工作空间和本地存储库来躲避那个子弹(尽管在 Maven 2.2.1 中,某些东西,例如POM 似乎总是从 ~/.m2/repository 中出来)额外的 SNAPSHOT 实际上只存在于单个构建中,然后它们会被丢弃(并从头开始再次下载)。所以我们已经看到这种方法一开始确实会占用更多空间,但它往往比将所有内容都从一个存储库中解决掉更稳定。此选项(在 Hudson 上)称为“使用私有 Maven 存储库”,当您选择使用 Maven 构建时,它位于项目配置的构建部分的高级按钮下。以下是该选项的帮助说明:
Normally, Hudson uses the local Maven repository as determined by Maven — the exact process seems to be undocumented, but it's ~/.m2/repository and can be overridden by in ~/.m2/settings.xml (see the reference for more details.) This normally means that all the jobs that are executed on the same node shares a single Maven repository. The upside of this is that you can save the disk space, but the downside of this is that sometimes those builds could interfere with each other. For example, you might end up having builds incorrectly succeed, just because your have all the dependencies in your local repository, despite that fact that none of the repositories in POM might have them.
There are also some reported problems regarding having concurrent Maven processes trying to use the same local repository.
When this option is checked, Hudson will tell Maven to use $WORKSPACE/.repository as the local Maven repository. This means each job will get its own isolated Maven repository just for itself. It fixes the above problems, at the expense of additional disk space consumption.
When using this option, consider setting up a Maven artifact manager so that you don't have to hit remote Maven repositories too often.
If you'd prefer to activate this mode in all the Maven jobs executed on Hudson, refer to the technique described here.
通常,Hudson 使用由 Maven 确定的本地 Maven 存储库——确切的过程似乎没有记录,但它是 ~/.m2/repository 并且可以在 ~/.m2/settings.xml 中被覆盖(更多详细信息请参阅参考资料.) 这通常意味着在同一节点上执行的所有作业共享一个 Maven 存储库。这样做的好处是可以节省磁盘空间,但坏处是有时这些构建可能会相互干扰。例如,您最终可能会错误地构建成功,仅仅因为您在本地存储库中拥有所有依赖项,尽管事实上 POM 中的所有存储库都没有这些依赖项。
也有一些关于让并发 Maven 进程尝试使用相同的本地存储库的报告问题。
选中此选项后,Hudson 将告诉 Maven 使用 $WORKSPACE/.repository 作为本地 Maven 存储库。这意味着每个作业都将获得自己独立的 Maven 存储库。它以额外的磁盘空间消耗为代价解决了上述问题。
使用此选项时,请考虑设置 Maven 工件管理器,以便您不必过于频繁地访问远程 Maven 存储库。
如果您希望在 Hudson 上执行的所有 Maven 作业中激活此模式,请参阅此处描述的技术。
Hope this helps - if it doesn't address your problem please let me know where I missed.
希望这会有所帮助 - 如果它不能解决您的问题,请告诉我我错过的地方。
回答by Cathy
This plugin removes project's artifacts from local repository. Useful to keep only one copy of large local snapshot.
此插件从本地存储库中删除项目的工件。仅保留一份大型本地快照的副本很有用。
<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>
回答by yurinadestin
Well I didn't like any of proposed solutions. Deleting maven cache often significantly increases network traffic and slows down build process. build-helper-maven-plugin helps only with one artifact, I wanted solution that can purge all outdated timestamped snapshot artifacts from local cache in one simple command. After few days of searching, I gave up and decided to write small program. The final program seems to be working quite well in our environment. So I decided to share it with others who may need such tool. Sources can be pulled from github: https://github.com/nadestin/tools/tree/master/MavenCacheCleanup
好吧,我不喜欢任何提议的解决方案。删除 Maven 缓存通常会显着增加网络流量并减慢构建过程。build-helper-maven-plugin 仅对一个工件有帮助,我想要的解决方案可以通过一个简单的命令从本地缓存中清除所有过时的时间戳快照工件。经过几天的搜索,我放弃了,决定写一个小程序。最终的程序似乎在我们的环境中运行良好。因此,我决定与可能需要此类工具的其他人分享。可以从 github 中提取源:https: //github.com/nadestin/tools/tree/master/MavenCacheCleanup
回答by vnov
In groovy, deleting timestamped files like artifact-0.0.1-20101204.150527-6.jar
can be very simple:
在 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()
}
}
Install Groovy, save the script into a file and schedule the execution at each week, start, logon, whatever suits you.
安装Groovy,将脚本保存到文件中并安排每周执行,启动,登录,任何适合您的。
Or, you can even wire the execution into maven build, using gmavenplus-plugin. Notice, how is the repository location set by maven into the property settings.localRepository
and then binded through configuration into variable repository
:
或者,您甚至可以使用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>
回答by vaquar khan
Add following parameter into your POM file
将以下参数添加到您的 POM 文件中
POM
聚甲醛
<configuration>
<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>
</configuration>
https://maven.apache.org/plugins/maven-dependency-plugin/copy-mojo.html
https://maven.apache.org/plugins/maven-dependency-plugin/copy-mojo.html
POM example
聚甲醛示例
<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>
Configure in Jenkins:
在詹金斯中配置:
// copy artifact
copyMavenArtifact(artifact: "commons-collections:commons-collections:3.2.2:jar", outputAbsoluteArtifactFilename: "${pwd()}/target/my-folder/commons-collections.jar")