From 92ca28e25af3383b5db9a79642fc57a2d9de5a90 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 14 Mar 2016 13:28:50 +0100 Subject: [PATCH 1/3] Use configuration of evicted nodes with cached resolution Consider a configuration where we have two projects, A and B. A has a library dependency on "a" % "b" % "1.0.0" % "compile->runtime" and "a" % "b" % "1.0.0" % "compile->runtime2" B depends on project A, and has a library dependency on "a" % "b" % "1.0.1" % "compile->runtime". Note that project B depends on a more recent version of "a" % "b" than project A, and that it depends ONLY on it's "runtime" configuration. However, when compiling project B, we expect to have on the classpath project A, and "a" % "b" % "1.0.1" % "compile->runtime" AND "a" % "b" % "1.0.1" % "compile->runtime2" because it is part of the compile configuration of project A. This commit changes the cached resolution engine so that it behaves like that, by first resolving dependencies on other project and then ensuring that the dependent project specifies dependencies on the same configurations. Mark test dependency-management/cached-resolution-configurations as passing. --- .../CachedResolutionResolveEngine.scala | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala b/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala index 6f4a69065..2e0a940b9 100644 --- a/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala +++ b/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala @@ -331,12 +331,41 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine { Left(new ResolveException(messages, failed, failedPaths)) } } - val results = mds map { + val (internal, external) = mds.partition { case (_, _, dd) => cache.internalDependency(dd, projectResolver).isDefined } + val internalResults = internal map { case (md, changing, dd) => cache.getOrElseUpdateMiniGraph(md, changing, logicalClock, miniGraphPath, cachedDescriptor, log) { doWork(md, dd) } } + val externalResults = external map { + case (md0, changing, dd) => + val configurationsInInternal = internalResults flatMap { + case Right(ur) => ur.allModules.flatMap { + case md => + val sameName = md.name == dd.getDependencyId.getName + val sameOrg = md.organization == dd.getDependencyId.getOrganisation + if (sameName && sameOrg) md.configurations + else None + } + case _ => Nil + } + + dd match { + case d: DefaultDependencyDescriptor => + configurationsInInternal foreach { c => + val configurations = c.split(";").map(_.split("->")) + configurations foreach { conf => d.addDependencyConfiguration(conf(0), conf(1)) } + } + + case _ => () + } + + // cache.getOrElseUpdateMiniGraph(md0, changing, logicalClock, miniGraphPath, cachedDescriptor, log) { + doWork(md0, dd) + // } + } + val results = internalResults ++ externalResults val uReport = mergeResults(md0, results, missingOk, System.currentTimeMillis - start, os, log) val cacheManager = getSettings.getResolutionCacheManager cacheManager.saveResolvedModuleDescriptor(md0) From ba274e05ac55e4ac5127b24a91fbf25f82c62512 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 11 Apr 2016 10:06:13 +0200 Subject: [PATCH 2/3] Re-enable caching and updating minigraph in cached resolution --- .../ivyint/CachedResolutionResolveEngine.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala b/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala index 2e0a940b9..6a2856792 100644 --- a/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala +++ b/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala @@ -361,9 +361,9 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine { case _ => () } - // cache.getOrElseUpdateMiniGraph(md0, changing, logicalClock, miniGraphPath, cachedDescriptor, log) { - doWork(md0, dd) - // } + cache.getOrElseUpdateMiniGraph(md0, changing, logicalClock, miniGraphPath, cachedDescriptor, log) { + doWork(md0, dd) + } } val results = internalResults ++ externalResults val uReport = mergeResults(md0, results, missingOk, System.currentTimeMillis - start, os, log) From 1756d7372486338e86856a6bce00531d1b95746e Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Tue, 24 May 2016 10:25:24 +0200 Subject: [PATCH 3/3] Workaround for sbt/sbt#2620 --- .../ivyint/CachedResolutionResolveEngine.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala b/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala index 6a2856792..892d4b8e4 100644 --- a/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala +++ b/librarymanagement/src/main/scala/sbt/internal/librarymanagement/ivyint/CachedResolutionResolveEngine.scala @@ -355,7 +355,10 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine { case d: DefaultDependencyDescriptor => configurationsInInternal foreach { c => val configurations = c.split(";").map(_.split("->")) - configurations foreach { conf => d.addDependencyConfiguration(conf(0), conf(1)) } + configurations foreach { conf => + try d.addDependencyConfiguration(conf(0), conf(1)) + catch { case _: Throwable => () } // An exception will be thrown if `conf(0)` doesn't exist. + } } case _ => ()