From ea9a2931f69e87fdcf5a8bce02940a30ea4ab56c Mon Sep 17 00:00:00 2001
From: William Benton <willb@redhat.com>
Date: Fri, 13 Dec 2013 11:39:09 -0600
Subject: [PATCH 1/2] Support Ivy 2.3.0-final.

This entailed modifying ResolutionCache and the CustomPomParser
to reflect changes to the ResolutionCacheManager interface and
DefaultExtendsDescriptor class between Ivy 2.3.0-rc1 and
2.3.0-rc2. Specifically,

1. ResolutionCacheManager now includes two additional methods
that needed implementations in ResolutionCache:
getResolvedModuleDescriptor(mrid: ModuleRevisionId) and
saveResolvedModuleDescriptor(md: ModuleDescriptor). I adapted
the implementations for these (which are expressed primarily in
terms of other interface methods) from Ivy 2.3.0's
DefaultResolutionCacheManager.

2. Instead of taking a ModuleRevisionIdentifier and a resolved
ModuleRevisionIdentifier as its first two arguments, the
DefaultExtendsDescriptor constructor now takes a
ModuleDescriptor. This was a trivial change.

Note that ResolutionCache.getResolvedModuleDescriptor does not
appear to be used by Ivy as sbt uses Ivy and there is thus no
test coverage for its implementation. Also note that the
DefaultResolutionCacheManager object created in
Update.configureResolutionCache now requires a reference to an
IvySettings object; DRCM expects this to be non-null.
---
 ivy/src/main/scala/sbt/CustomPomParser.scala |  2 +-
 ivy/src/main/scala/sbt/Ivy.scala             |  2 +-
 ivy/src/main/scala/sbt/ResolutionCache.scala | 27 ++++++++++++++++++++++++++-
 launch/src/main/scala/xsbt/boot/Update.scala |  4 +++-
 project/Util.scala                           |  2 +-
 5 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/ivy/src/main/scala/sbt/CustomPomParser.scala b/ivy/src/main/scala/sbt/CustomPomParser.scala
index 34147d9..7023ab8 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 6154bdb..e1dca53 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 ab69344..1243420 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 a39a70f..6c8c9f3 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 afddf87..13f99a0 100644
--- a/project/Util.scala
+++ b/project/Util.scala
@@ -167,7 +167,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))
-- 
1.8.3.4 (Apple Git-47)

