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

现在,maven-3为快照构件的 < uniqueVersion > false 执行了 放下支架,看起来您确实需要使用带时间戳的 SNAPSHOTS。尤其是 m2eclipse,它在内部使用了 maven 3,似乎会受到影响,当 SNAPSHOTS 不是唯一的时候更新快照不起作用。

将所有快照设置为 uniqueVersion = false 似乎是最好的 练习过

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

问题在于本地开发人员工作站。他们的本地存储库使用独特的快照快速增长 非常

如何处理这个问题?

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

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

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

更新:

为了验证这种行为并提供更多信息,我设置了一个小型的 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>

乙:

<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”上运行“部署”时

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

在构建大量快照的环境中(想想 Hudson server...) ,本地存储库将用旧版本 很快填充

更新2:

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

  • Mvn 使用 maven 2.2.1进行部署:

计算机上的本地存储库 A 确实包含 Snapshot.jar + fast-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 + fast-timestamp.jar: (
  • 使用外部 maven 2.2.1运行包目标-> 本地存储库具有 Snapshot.jar + fast-timestamp.jar: (

好的,下一次尝试使用 maven3.0.1(在删除项目 a 的所有痕迹之后)

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

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

    De Glauche 一 0.0.1-快照

    <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 + fast-timestamp.jar: (

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

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

我做错了什么?

更新3

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

72484 次浏览

The <uniqueVersion> configuration applied to artifacts that were deployed (via mvn deploy) to a Maven repository such as 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.

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

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.

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.

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, Maven will 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

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.

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.

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:

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.

Hope this helps - if it doesn't address your problem please let me know where I missed.

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>

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

In groovy, deleting timestamped files like artifact-0.0.1-20101204.150527-6.jar can be very simple:

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.

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:

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

Add following parameter into your POM file

POM

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

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