mirror of https://github.com/sbt/sbt.git
Fixes #1639. Fixes cached resolution interacting with force()
When conflicts are found for a given module, a forced one is selected before conflict manager kicks in. The problem is that DependencyDescriptor seems to mark transitive forced dependency as forced as well, so the actual forced dependency are sometimes not prioritized. To work around this, I’ve introduced a mixin called SbtDefaultDependencyDescriptor, which carries around ModuleID to detect direct dependencies.
This commit is contained in:
parent
c2b4c0ec94
commit
832bf601b5
|
|
@ -4,7 +4,7 @@
|
|||
package sbt
|
||||
|
||||
import Resolver.PluginPattern
|
||||
import ivyint.{ CachedResolutionResolveEngine, CachedResolutionResolveCache }
|
||||
import ivyint.{ CachedResolutionResolveEngine, CachedResolutionResolveCache, SbtDefaultDependencyDescriptor }
|
||||
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
|
|
@ -570,7 +570,9 @@ private[sbt] object IvySbt {
|
|||
/** Transforms an sbt ModuleID into an Ivy DefaultDependencyDescriptor.*/
|
||||
def convertDependency(moduleID: DefaultModuleDescriptor, dependency: ModuleID, parser: CustomXmlParser.CustomParser): DefaultDependencyDescriptor =
|
||||
{
|
||||
val dependencyDescriptor = new DefaultDependencyDescriptor(moduleID, toID(dependency), dependency.isForce, dependency.isChanging, dependency.isTransitive)
|
||||
val dependencyDescriptor = new DefaultDependencyDescriptor(moduleID, toID(dependency), dependency.isForce, dependency.isChanging, dependency.isTransitive) with SbtDefaultDependencyDescriptor {
|
||||
def dependencyModuleId = dependency
|
||||
}
|
||||
dependency.configurations match {
|
||||
case None => // The configuration for this dependency was not explicitly specified, so use the default
|
||||
parser.parseDepsConfs(parser.getDefaultConf, dependencyDescriptor)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import module.id.{ ModuleRevisionId, ModuleId => IvyModuleId }
|
|||
import report.{ ArtifactDownloadReport, ConfigurationResolveReport, ResolveReport }
|
||||
import resolve.{ IvyNode, IvyNodeCallers }
|
||||
import IvyNodeCallers.{ Caller => IvyCaller }
|
||||
import ivyint.SbtDefaultDependencyDescriptor
|
||||
|
||||
object IvyRetrieve {
|
||||
def reports(report: ResolveReport): Seq[ConfigurationResolveReport] =
|
||||
|
|
@ -77,11 +78,14 @@ object IvyRetrieve {
|
|||
case x if nonEmptyString(x).isDefined => x
|
||||
}
|
||||
val ddOpt = Option(caller.getDependencyDescriptor)
|
||||
val (extraAttributes, isForce, isChanging, isTransitive) = ddOpt match {
|
||||
case Some(dd) => (toExtraAttributes(dd.getExtraAttributes), dd.isForce, dd.isChanging, dd.isTransitive)
|
||||
case None => (Map.empty[String, String], false, false, true)
|
||||
val (extraAttributes, isForce, isChanging, isTransitive, isDirectlyForce) = ddOpt match {
|
||||
case Some(dd: SbtDefaultDependencyDescriptor) =>
|
||||
val mod = dd.dependencyModuleId
|
||||
(toExtraAttributes(dd.getExtraAttributes), mod.isForce, mod.isChanging, mod.isTransitive, mod.isForce)
|
||||
case Some(dd) => (toExtraAttributes(dd.getExtraAttributes), dd.isForce, dd.isChanging, dd.isTransitive, false)
|
||||
case None => (Map.empty[String, String], false, false, true, false)
|
||||
}
|
||||
new Caller(m, callerConfigurations, extraAttributes, isForce, isChanging, isTransitive)
|
||||
new Caller(m, callerConfigurations, extraAttributes, isForce, isChanging, isTransitive, isDirectlyForce)
|
||||
}
|
||||
val revId = dep.getResolvedId
|
||||
val moduleId = toModuleID(revId)
|
||||
|
|
|
|||
|
|
@ -190,7 +190,8 @@ final class Caller(
|
|||
val callerExtraAttributes: Map[String, String],
|
||||
val isForceDependency: Boolean,
|
||||
val isChangingDependency: Boolean,
|
||||
val isTransitiveDependency: Boolean) {
|
||||
val isTransitiveDependency: Boolean,
|
||||
val isDirectlyForceDependency: Boolean) {
|
||||
override def toString: String =
|
||||
s"$caller"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ private[sbt] class CachedResolutionResolveCache() {
|
|||
val mds =
|
||||
if (mrid0.getOrganisation == sbtOrgTemp) Vector(md0)
|
||||
else buildArtificialModuleDescriptors(md0, prOpt) map { _._1 }
|
||||
|
||||
updateReportCache.remove(md0.getModuleRevisionId)
|
||||
directDependencyCache.remove(md0.getModuleRevisionId)
|
||||
mds foreach { md =>
|
||||
updateReportCache.remove(md.getModuleRevisionId)
|
||||
directDependencyCache.remove(md.getModuleRevisionId)
|
||||
|
|
@ -186,6 +189,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
|
|||
val miniGraphPath = depDir / "module"
|
||||
val cachedDescriptor = getSettings.getResolutionCacheManager.getResolvedIvyFileInCache(md0.getModuleRevisionId)
|
||||
val cache = cachedResolutionResolveCache
|
||||
cache.directDependencyCache.remove(md0.getModuleRevisionId)
|
||||
val mds = cache.buildArtificialModuleDescriptors(md0, projectResolver)
|
||||
def doWork(md: ModuleDescriptor): Either[ResolveException, UpdateReport] =
|
||||
{
|
||||
|
|
@ -292,10 +296,13 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
|
|||
val name = head.module.name
|
||||
log.debug(s"- conflict in $rootModuleConf:$organization:$name " + (conflicts map { _.module }).mkString("(", ", ", ")"))
|
||||
def useLatest(lcm: LatestConflictManager): (Vector[ModuleReport], Vector[ModuleReport], String) =
|
||||
conflicts find { m =>
|
||||
(conflicts find { m =>
|
||||
m.callers.exists { _.isDirectlyForceDependency }
|
||||
} orElse (conflicts find { m =>
|
||||
m.callers.exists { _.isForceDependency }
|
||||
} match {
|
||||
})) match {
|
||||
case Some(m) =>
|
||||
log.debug(s"- forced dependency: $m")
|
||||
(Vector(m), conflicts filterNot { _ == m } map { _.copy(evicted = true, evictedReason = Some(lcm.toString)) }, lcm.toString)
|
||||
case None =>
|
||||
val strategy = lcm.getStrategy
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
package sbt
|
||||
package ivyint
|
||||
|
||||
import org.apache.ivy.core
|
||||
import core.module.descriptor.DefaultDependencyDescriptor
|
||||
|
||||
trait SbtDefaultDependencyDescriptor { self: DefaultDependencyDescriptor =>
|
||||
def dependencyModuleId: ModuleID
|
||||
}
|
||||
Loading…
Reference in New Issue