Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
219 lines (201 sloc) 8.432 kb
/**
* This groovy scripts can be used to clean up your local maven repository without the need to throw it away completely.
*
* You can tweak the script by changing the Configuration object. Parameters that can be changed are discussed below.
* The defaults in the script are for safety, we by default show everything and do nothing
*
* homeFolder : The user home folder taken from the system property
* path : The home folder as mentioned above together /.m2/repository, the default location of a maven repository
* dryRun : true, so we do not actually delete something by default
* printDetails : true, to check what will happen if you run this script without the dry run.
* maxAgeSnapshotsInDays : 60, older snapshots are removed
* maxAgeInDays : 90, older versions are removed if a higher version is available
* versionsToKeep : ["3.1.0.M1"], array of versions that we do not want to delete (Not used for SNAPSHOTS)
* snapshotsOnly : true, by default we only check the snapshots, change if you want to check the other versions as well
*
* @author Jettro Coenradie
*/
/*
* Here we specify the defaults of the script
*/
now = new Date()
configuration = new Configuration()
cleanedSize = 0
details = []
directoryFilter = new DirectoryFilter()
nonSnapshotDirectoryFilter = new NonSnapshotDirectoryFilter()
def class Configuration {
def homeFolder = System.getProperty("user.home")
def path = homeFolder + "/.m2/repository"
def dryRun = true
def printDetails = true
def maxAgeSnapshotsInDays = 60
def maxAgeInDays = 90
def versionsToKeep = ["3.1.0.M1"]
def snapshotsOnly = true
}
/*
* Main Execution of the script
*/
printConfiguration()
def mainDir = new File(configuration.path)
if (!mainDir.directory) {
printf("The provided directory \"%s\" is not a directory", configuration.path)
System.exit(-1)
}
cleanMavenRepository(mainDir);
printResultOfCleanAction()
/*
* Helper functions
*/
private def cleanMavenRepository(File file) {
def lastModified = new Date(file.lastModified());
def ageInDays = now - lastModified;
def directories = file.listFiles(directoryFilter);
if (directories.length > 0) {
directories.each {
cleanMavenRepository(it);
}
} else {
if (ageInDays > configuration.maxAgeSnapshotsInDays && file.canonicalPath.endsWith("-SNAPSHOT")) {
int size = removeDirAndReturnFreedKBytes(file)
details.add("About to remove directory $file.canonicalPath with total size $size and $ageInDays days old");
} else if (ageInDays > configuration.maxAgeInDays && !file.canonicalPath.endsWith("-SNAPSHOT") && !configuration.snapshotsOnly) {
String highest = obtainHighestVersionOfArtifact(file)
if (file.name != highest && !configuration.versionsToKeep.contains(file.name)) {
int size = removeDirAndReturnFreedKBytes(file)
details.add("About to remove directory $file.canonicalPath with total size $size and $ageInDays days old and not highest version $highest");
}
}
}
}
/**
* Removes the directory if this is not a dry run. Calculates the amount of Kb that was freed and returns it.
* @param file File representing a directory to remove
* @return integer representing the amount of Kb that was freed
*/
private int removeDirAndReturnFreedKBytes(File file) {
int size = calculateDirectorySize(file)
cleanedSize += size
if (!configuration.dryRun) {
file.deleteDir();
}
return size
}
/**
* Returns the string representation of the artifact with the highest version
* @param file File repsenting a directory to check for the highest version of artifact
* @return String representing the highest version
*/
private String obtainHighestVersionOfArtifact(File file) {
def folderWithVersions = file.parentFile
// Keep only the highest version
def versionsFolders = folderWithVersions.listFiles(nonSnapshotDirectoryFilter)
def highest = '0'
versionsFolders.each {
if (higherThan(highest, it.name)) {
highest = it.name
}
}
return highest
}
/**
* True if newVersion > than highestVersion. Higher means if the tokenized string is higher in one of the elements
* starting from the left. If the token of the string is a pure number, we compare numbers. If (part of) it is a
* we compare strings. Yes this could mean problems in very special cases. Therefore we love people that stick to
* maven standards. There are some special cases, they are documented below.
* - If an artifact ends with RELEASE, by default we value it higher than another artifact
*
* examples for strings that we value as a release are:
* 3.0.0.RELEASE, 2.5.6, 2.3.4-beta1
*
* @param highestVersion String representing the current highest version
* @param newVersion String to compare with the highest version
* @return true if the newVersion is higher than the current highestVersion
*/
private boolean higherThan(highestVersion, newVersion) {
def highestArr = highestVersion.tokenize('.')
def newArr = newVersion.tokenize('.')
if (highestVersion.endsWith("RELEASE") && !newVersion.endsWith("RELEASE")) {
return false
}
return compareTwoIntegersInArray(highestArr, newArr, 0)
}
/**
* Utility function that is used recursive to find the highest of two items in an array on the same position. If they are
* equal, compare the next item in the array if available. If the first item of an array is teh same and one of the two
* items has only one item in the array, the other one wins.
* @param highestArr Array containing the elements of the current highest value
* @param newArr Array containing the elements of the value to compare with the highest value
* @param counter Integer representing the number in the array to compare (starting with 0)
* @return true if the newArr is higher than the highestArray
*/
private boolean compareTwoIntegersInArray(highestArr, newArr, counter) {
def counterPlus1 = counter + 1
if (highestArr[counter] == newArr[counter]) {
if (highestArr.size() > counterPlus1 && newArr.size() > counterPlus1) {
return compareTwoIntegersInArray(highestArr, newArr, counterPlus1)
} else if (newArr.size() > counterPlus1) {
return true
}
} else {
def highest = highestArr[counter]
def newest = newArr[counter]
if (highest.isInteger() && newest.isInteger()) {
if (highest.toInteger() < newest.toInteger()) {
return true
}
} else {
if (highest < newest) {
return true
}
}
}
return false
}
/**
* Returns the size in Kbytes of the content of the provided directory
*
* @param file File that must be a directory to calculate the size for.
* @return Integer representing the size in Kb of the provided directory
*/
private int calculateDirectorySize(File file) {
def files = file.listFiles()
def size = 0
files.each {
size += it.size()
}
return size
}
private def printConfiguration() {
println "*******************************************************************************"
println "* About the clean a maven repository"
printf("* Start cleaning at path: %s\n", configuration.path)
printf("* Remove all snapshots that are older than %d days\n", configuration.maxAgeSnapshotsInDays)
printf("* Remove all versions that are older than %d days and do have a higher version available\n", configuration.maxAgeInDays)
if (configuration.dryRun) {
println("* We are going to do a dry run")
}
if (configuration.snapshotsOnly) {
println("* We only remove snapshots, no versioned artifacts are deleted")
}
}
private def printResultOfCleanAction() {
printf("* Total size cleaned is %dk\n", Math.round(cleanedSize / 1024))
println "*******************************************************************************"
if (configuration.printDetails) {
details.each {
println it
}
}
}
def class DirectoryFilter implements FileFilter {
boolean accept(File file) {
return file.directory;
}
}
def class NonSnapshotDirectoryFilter implements FileFilter {
boolean accept(File file) {
return file.directory && !file.name.endsWith("-SNAPSHOT")
}
}
Jump to Line
Something went wrong with that request. Please try again.