diff --git a/ivy/src/main/scala/sbt/CustomPomParser.scala b/ivy/src/main/scala/sbt/CustomPomParser.scala index 34147d933..7023ab8d9 100644 --- a/ivy/src/main/scala/sbt/CustomPomParser.scala +++ b/ivy/src/main/scala/sbt/CustomPomParser.scala @@ -203,7 +203,7 @@ object CustomPomParser val unique = IvySbt.mergeDuplicateDefinitions(withExtra) unique foreach dmd.addDependency - for( ed <- md.getInheritedDescriptors) dmd.addInheritedDescriptor( new DefaultExtendsDescriptor( mrid, resolvedMrid, ed.getLocation, ed.getExtendsTypes) ) + for( ed <- md.getInheritedDescriptors) dmd.addInheritedDescriptor( new DefaultExtendsDescriptor( md, ed.getLocation, ed.getExtendsTypes) ) for( conf <- md.getConfigurations) { dmd.addConfiguration(conf) for(art <- md.getArtifacts(conf.getName)) { diff --git a/ivy/src/main/scala/sbt/Ivy.scala b/ivy/src/main/scala/sbt/Ivy.scala index 6154bdbe8..e1dca53ae 100644 --- a/ivy/src/main/scala/sbt/Ivy.scala +++ b/ivy/src/main/scala/sbt/Ivy.scala @@ -310,7 +310,7 @@ private object IvySbt private[this] def configureResolutionCache(settings: IvySettings, localOnly: Boolean, resCacheDir: Option[File]) { val base = resCacheDir getOrElse settings.getDefaultResolutionCacheBasedir - settings.setResolutionCacheManager(new ResolutionCache(base)) + settings.setResolutionCacheManager(new ResolutionCache(base, settings)) } // set the artifact resolver to be the main resolver. // this is because sometimes the artifact resolver saved in the cache is not correct diff --git a/ivy/src/main/scala/sbt/ResolutionCache.scala b/ivy/src/main/scala/sbt/ResolutionCache.scala index ab693445d..d79f25a4c 100644 --- a/ivy/src/main/scala/sbt/ResolutionCache.scala +++ b/ivy/src/main/scala/sbt/ResolutionCache.scala @@ -1,18 +1,24 @@ package sbt import java.io.File +import java.io.FileInputStream +import java.util.Properties import org.apache.ivy.core +import org.apache.ivy.plugins.parser import core.IvyPatternHelper +import core.settings.IvySettings import core.cache.{CacheMetadataOptions, DefaultRepositoryCacheManager, DefaultResolutionCacheManager, ResolutionCacheManager} import core.module.id.ModuleRevisionId +import core.module.descriptor.ModuleDescriptor import ResolutionCache.{Name, ReportDirectory, ResolvedName, ResolvedPattern} +import parser.xml.XmlModuleDescriptorParser /** Replaces the standard Ivy resolution cache in order to: * 1. Separate cached resolved Ivy files from resolution reports, making the resolution reports easier to find. * 2. Have them per-project for easier cleaning (possible with standard cache, but central to this custom one). * 3. Cache location includes extra attributes so that cross builds of a plugin do not overwrite each other. */ -private[sbt] final class ResolutionCache(base: File) extends ResolutionCacheManager +private[sbt] final class ResolutionCache(base: File, settings: IvySettings) extends ResolutionCacheManager { private[this] def resolvedFileInCache(m: ModuleRevisionId, name: String, ext: String): File = { val p = ResolvedPattern @@ -35,6 +41,25 @@ private[sbt] final class ResolutionCache(base: File) extends ResolutionCacheMana new File(reportBase, resolveId + "-" + conf + ".xml") def getConfigurationResolveReportsInCache(resolveId: String): Array[File] = IO.listFiles(reportBase).filter(_.getName.startsWith(resolveId + "-")) + + // XXX: this method is required by ResolutionCacheManager in Ivy 2.3.0 final, + // but it is apparently unused by Ivy as sbt uses Ivy. Therefore, it is + // unexercised in tests. Note that the implementation of this method in Ivy 2.3.0's + // DefaultResolutionCache also resolves parent properties for a given mrid + def getResolvedModuleDescriptor(mrid: ModuleRevisionId): ModuleDescriptor = { + val ivyFile = getResolvedIvyFileInCache(mrid) + if (!ivyFile.exists()) { + throw new IllegalStateException("Ivy file not found in cache for " + mrid + "!") + } + + return XmlModuleDescriptorParser.getInstance().parseDescriptor(settings, ivyFile.toURI().toURL(), false) + } + + def saveResolvedModuleDescriptor(md: ModuleDescriptor): Unit = { + val mrid = md.getResolvedModuleRevisionId + val cachedIvyFile = getResolvedIvyFileInCache(mrid) + md.toIvyFile(cachedIvyFile) + } } private[sbt] object ResolutionCache { diff --git a/launch/src/main/scala/xsbt/boot/Update.scala b/launch/src/main/scala/xsbt/boot/Update.scala index a39a70fa9..92e1bec92 100644 --- a/launch/src/main/scala/xsbt/boot/Update.scala +++ b/launch/src/main/scala/xsbt/boot/Update.scala @@ -286,7 +286,9 @@ final class Update(config: UpdateConfiguration) private[this] def configureResolutionCache(settings: IvySettings) { resolutionCacheBase.mkdirs() - settings.setResolutionCacheManager(new DefaultResolutionCacheManager(resolutionCacheBase)) + val drcm = new DefaultResolutionCacheManager(resolutionCacheBase) + drcm.setSettings(settings) + settings.setResolutionCacheManager(drcm) } private[this] def configureRepositoryCache(settings: IvySettings) { diff --git a/project/Util.scala b/project/Util.scala index 9b7595a3c..a5b0cbb4f 100644 --- a/project/Util.scala +++ b/project/Util.scala @@ -168,7 +168,7 @@ object Common def lib(m: ModuleID) = libraryDependencies += m lazy val jlineDep = "jline" % "jline" % "2.11" lazy val jline = lib(jlineDep) - lazy val ivy = lib("org.apache.ivy" % "ivy" % "2.3.0-rc1") + lazy val ivy = lib("org.apache.ivy" % "ivy" % "2.3.0") lazy val httpclient = lib("commons-httpclient" % "commons-httpclient" % "3.1") lazy val jsch = lib("com.jcraft" % "jsch" % "0.1.46" intransitive() ) lazy val sbinary = libraryDependencies <+= Util.nightly211(n => "org.scala-tools.sbinary" % "sbinary" % "0.4.2" cross(if(n) CrossVersion.full else CrossVersion.binary))