如何从maven存储库中清除旧的依赖项?

时间:2013-10-11 05:10:53

标签: java maven dependencies repository dependency-management

我在.m2文件夹中有太多文件,其中maven存储下载的依赖项。有没有办法清理所有旧的依赖项?例如,如果存在3个不同版本的依赖关系:1,2和3,清理后必须只有第3个版本。我如何才能对.m2文件夹中的所有依赖项执行此操作?

9 个答案:

答案 0 :(得分:24)

简短回答 - 已删除{user.home}中的.m2文件夹。例如。在Windows 10用户主页是C:\Users\user1。使用mvn clean package重新构建项目。只保留那些项目所需的依赖项。

长答案 - .m2文件夹就像一个普通的文件夹,文件夹的内容是从不同的项目构建的。我认为没有办法自动弄清楚哪个库是“旧的”。事实上,旧的是一个模糊的词。在项目中使用先前版本的库时可能有很多原因,因此无法确定哪一个未使用。

您所能做的就是删除.m2文件夹并重新构建所有项目,然后该文件夹将自动构建所有必需的库。

如果您只关心要在所有项目中使用的特定版本的库;重要的是项目的pom也应该更新到最新版本。即如果不同的POM引用了库的不同版本,则所有版本都将在.m2中下载。

答案 1 :(得分:5)

给定maven项目的POM文件,您可以使用Apache Maven Dependency Plugin删除本地存储库中的所有依赖项(默认情况下为〜/ .m2 / respository)。

它包含dependency:purge-local-repository功能,可从本地存储库中删除项目依赖项,并可选择重新解析它们。

要清理本地依赖项,您只需使用可选参数reResolve并将其设置为false,因为默认情况下它设置为true。

此命令行调用应该起作用:

mvn dependency:purge-local-repository -DreResolve=false

答案 2 :(得分:4)

  1. 下载项目的所有实际依赖项

    find your-projects-dir -name pom.xml -exec mvn -f '{}' dependency:resolve
    
  2. 将您的本地maven存储库移至临时位置

    mv ~/.m2 ~/saved-m2
    
  3. 将所有文件maven-metadata-central.xml *从已保存的存储库重命名为maven-metadata.xml *

    find . -type f -name "maven-metadata-central.xml*" -exec rename -v -- 's/-central//' '{}' \;
    
  4. 要将本地存储库的修改后的副本设置为镜像,请使用以下内容创建目录〜/ .m2和文件〜/ .m2 / settings.xml(替换 用户 与您的用户名):

    <settings>
     <mirrors>
      <mirror>
       <id>mycentral</id>
       <name>My Central</name>
       <url>file:/home/user/saved-m2/</url>
       <mirrorOf>central</mirrorOf>
      </mirror>
     </mirrors>
    </settings>
    
  5. 再次解决项目依赖关系:

    find your-projects-dir -name pom.xml -exec mvn -f '{}' dependency:resolve
    
  6. 现在您拥有本地maven存储库,其中包含最少的必要工件。从配置文件和文件系统中删除本地镜像。

答案 3 :(得分:3)

问这个问题已经6年多了,但是我没有找到任何工具来清理我的存储库。所以我用python写了一个我自己,以摆脱旧的罐子。也许对某人有用:

from os.path import isdir
from os import listdir
import re
import shutil

dry_run = False #  change to True to get a log of what will be removed
m2_path = '/home/jb/.m2/repository/' #  here comes your repo path
version_regex = '^\d[.\d]*$'


def check_and_clean(path):
    files = listdir(path)
    for file in files:
        if not isdir('/'.join([path, file])):
            return
    last = check_if_versions(files)
    if last is None:
        for file in files:
            check_and_clean('/'.join([path, file]))
    elif len(files) == 1:
        return
    else:
        print('update ' + path.split(m2_path)[1])
        for file in files:
            if file == last:
                continue
            print(file + ' (newer version: ' + last + ')')
            if not dry_run:
                shutil.rmtree('/'.join([path, file]))


def check_if_versions(files):
    if len(files) == 0:
        return None
    last = ''
    for file in files:
        if re.match(version_regex, file):
            if last == '':
                last = file
            if len(last.split('.')) == len(file.split('.')):
                for (current, new) in zip(last.split('.'), file.split('.')):
                    if int(new) > int(current):
                        last = file
                        break
                    elif int(new) < int(current):
                        break
            else:
                return None
        else:
            return None
    return last


check_and_clean(m2_path)

它在.m2存储库中进行递归搜索,并且如果找到不同版本所在的目录,则会删除所有版本,但最新版本除外。

假设您的.m2存储库中的某处有以下树:

.
└── antlr
    ├── 2.7.2
    │   ├── antlr-2.7.2.jar
    │   ├── antlr-2.7.2.jar.sha1
    │   ├── antlr-2.7.2.pom
    │   ├── antlr-2.7.2.pom.sha1
    │   └── _remote.repositories
    └── 2.7.7
        ├── antlr-2.7.7.jar
        ├── antlr-2.7.7.jar.sha1
        ├── antlr-2.7.7.pom
        ├── antlr-2.7.7.pom.sha1
        └── _remote.repositories

然后该脚本删除了antlr的2.7.2版本,剩下的是:

.
└── antlr
    └── 2.7.7
        ├── antlr-2.7.7.jar
        ├── antlr-2.7.7.jar.sha1
        ├── antlr-2.7.7.pom
        ├── antlr-2.7.7.pom.sha1
        └── _remote.repositories

如果您正在使用的任何旧版本将被删除。可以使用Maven(或其他管理依赖项的工具)轻松恢复它。

通过设置dry_run = False,您可以获取要删除的日志,而无需实际删除。输出将如下所示:

update /org/projectlombok/lombok
1.18.2 (newer version: 1.18.6)
1.16.20 (newer version: 1.18.6)

这意味着,将删除lombok的1.16.20和1.18.2版本,而将保持1.18.6不变。

可以在我的github(最新版本)上找到该文件。

答案 4 :(得分:1)

我也想从我的Maven存储库中删除旧的依赖项。我想过只运行Florian的答案,但是我想要一些我可以反复运行的东西,而不记得一个长的linux片段,我想要一些具有一点可配置性的东西 - 更多的是程序,而不是一串unix命令所以我采用了基本的想法并将其变成了一个(相对较小的)Ruby程序,它根据上次访问时间删除旧的依赖项。

它不会删除“旧版本”,但由于您实际上可能有两个不同的活动项目和两个不同版本的依赖项,所以无论如何都不会做我想要的。相反,像Florian的回答一样,它删除了最近未访问的依赖项。

如果你想尝试一下,你可以:

  1. 访问GitHub repository
  2. 克隆存储库,或下载源
  3. 可选择检查代码以确保其不是恶意的
  4. 运行bin/mvnclean
  5. 有一些选项可以覆盖默认的Maven存储库,忽略文件,设置阈值日期,但是您可以在GitHub上的README中阅读这些选项。

    在我做了一些工作之后,我可能会在某些时候把它打包成Ruby gem,这样可以简化问题(gem install mvnclean; mvnclean),如果你已经安装了Ruby并且可以运行。

答案 5 :(得分:1)

只需清理.m2 - &gt;存储库文件夹下的每个内容。当您构建项目时,所有依赖项都会加载到此处。

在您的情况下,您的项目可能是您之前使用旧版本的任何依赖项,现在版本已升级。更好地​​清理.m2文件夹并使用mvn clean install构建项目。

现在,将在此文件夹中下载与最新版本模块的依赖关系。

答案 6 :(得分:1)

我确实花了几个小时来研究这个问题,答案很多都依赖于 atime(这是 UNIX 系统上的最后访问时间),这是一个不可靠的解决方案,原因有两个:< /p>

  1. 大多数 UNIX 系统(包括 Linux 和 macOS)最多不定期地更新 atime,这是有原因的:atime 的完整实现意味着整个文件系统将减慢每次读取文件时都必须更新(即写入磁盘)atime,而且如此大量的更新会很快磨损现代高性能 SSD 驱动器
  2. 在 CI/CD 环境中,用于构建 Maven 项目的 VM 将从共享存储中恢复其 Maven 存储库,这反过来会使 atime 设置为“最近”值< /li>

因此,我创建了一个 Maven 存储库清理器并使其在 https://github.com/alitokmen/maven-repository-cleaner/ 上可用。 bash maven-repository-cleaner.sh 脚本有一个函数 cleanDirectory,它是一个循环遍历 ~/.m2/repository/ 的递归函数,并执行以下操作:

  • 当子目录不是版本号时,它会深入该子目录进行分析
  • 当一个目录的子目录看起来是版本号时,它只会删除所有较低的版本

实际上,如果您有一个层次结构,例如:

  • artifact-group
    • artifact-name
      • 1.8
      • 1.10
      • 1.2

... maven-repository-cleaner.sh 脚本将:

  1. 导航到artifact-group
  2. artifact-group 中,导航至 artifact-name
  3. artifact-name中,删除子文件夹1.81.2,因为1.10优于1.21.8

因此这与 AndronicusPavan Kumar 提供的解决方案非常相似,不同之处在于这是作为 Shell 脚本编写的。要在您的 CI/CD 平台(或任何其他形式的 UNIX 系统)上运行该工具,只需在构建的开头或结尾使用以下三行:

wget https://raw.githubusercontent.com/alitokmen/maven-repository-cleaner/main/maven-repository-cleaner.sh
chmod +x maven-repository-cleaner.sh
./maven-repository-cleaner.sh

答案 7 :(得分:0)

我想出了一个实用程序,并在GitHub上托管,以清理本地Maven存储库中的旧版本库。该实用程序在其默认执行时会删除所有旧版本的工件,只留下最新版本。 (可选)它可以删除所有快照,源,javadoc,还可以在此过程中强制/排除组或工件。此跨平台还支持基于上次访问/下载日期的基于日期的删除。

https://github.com/techpavan/mvn-repo-cleaner

答案 8 :(得分:0)

您需要复制项目所需的依赖项。 掌握这些内容后,请清除嵌入到<dependency>标签中的所有<dependencies>标签 从项目中的POM.XML文件中。

保存文件后,您的Libraries中将不会显示 Maven依赖项。 然后,请粘贴您先前复制的<dependency>

所需的jar将由Maven自动下载,您也可以在 保存文件后生成的 Maven依赖项 Libraries

谢谢。