diff --git a/ivy/src/main/scala/sbt/Ivy.scala b/ivy/src/main/scala/sbt/Ivy.scala index 0414cb0c5..9260f3ed1 100644 --- a/ivy/src/main/scala/sbt/Ivy.scala +++ b/ivy/src/main/scala/sbt/Ivy.scala @@ -7,6 +7,7 @@ import Resolver.PluginPattern import java.io.File import java.net.URI +import java.text.ParseException import java.util.concurrent.Callable import java.util.{Collection, Collections => CS} import CS.singleton @@ -23,7 +24,9 @@ import core.settings.IvySettings import plugins.latest.LatestRevisionStrategy import plugins.matcher.PatternMatcher import plugins.parser.m2.PomModuleDescriptorParser +import plugins.repository.ResourceDownloader import plugins.resolver.{ChainResolver, DependencyResolver} +import plugins.resolver.util.ResolvedResource import util.{Message, MessageLogger} import util.extendable.ExtendableItem @@ -327,17 +330,42 @@ private object IvySbt } } } + /** This is overridden to delete outofdate artifacts of changing modules that are not listed in the metadata. + * This occurs for artifacts with classifiers, for example. */ + @throws(classOf[ParseException]) + override def cacheModuleDescriptor(resolver: DependencyResolver, mdRef: ResolvedResource, dd: DependencyDescriptor, moduleArtifact: IArtifact, downloader: ResourceDownloader, options: CacheMetadataOptions): ResolvedModuleRevision = + { + val rmr = super.cacheModuleDescriptor(resolver, mdRef, dd, moduleArtifact, downloader, options) + val mrid = moduleArtifact.getModuleRevisionId + // only handle changing modules whose metadata actually changed. + // Typically, the publication date in the metadata has to change to get here. + if(rmr.getReport != null && rmr.getReport.isSearched && isChanging(dd, mrid)) { + // this is the locally cached metadata as originally retrieved (e.g. the pom) + val original = rmr.getReport.getOriginalLocalFile + if(original != null) { + // delete all files in subdirectories that are older than the original metadata file + val lm = original.lastModified + val indirectFiles = PathFinder(original.getParentFile).*(DirectoryFilter).**(-DirectoryFilter).get.toList + val older = indirectFiles.filter(f => f.lastModified < lm).toList + Message.verbose("Deleting additional old artifacts from cache for changed module " + mrid + older.mkString(":\n\t", "\n\t", "")) + IO.delete(older) + } + } + rmr + } + def isChanging(dd: DependencyDescriptor, requestedRevisionId: ModuleRevisionId): Boolean = + dd.isChanging || requestedRevisionId.getRevision.contains("-SNAPSHOT") } manager.setArtifactPattern(PluginPattern + manager.getArtifactPattern) manager.setDataFilePattern(PluginPattern + manager.getDataFilePattern) manager.setIvyPattern(PluginPattern + manager.getIvyPattern) manager.setUseOrigin(true) if(localOnly) - manager.setDefaultTTL(java.lang.Long.MAX_VALUE); + manager.setDefaultTTL(java.lang.Long.MAX_VALUE) else { - manager.setChangingMatcher(PatternMatcher.REGEXP); - manager.setChangingPattern(".*-SNAPSHOT"); + manager.setChangingMatcher(PatternMatcher.REGEXP) + manager.setChangingPattern(".*-SNAPSHOT") } settings.addRepositoryCacheManager(manager) settings.setDefaultRepositoryCacheManager(manager)