This commit is contained in:
Eugene Yokota 2022-01-30 03:08:24 -05:00
parent a4ce8db55b
commit a8f2b1f636
34 changed files with 570 additions and 515 deletions

View File

@ -34,34 +34,33 @@ private[sbt] object JsonUtil {
UpdateReportLite(ur.configurations map { cr =>
ConfigurationReportLite(
cr.configuration.name,
cr.details map {
oar =>
OrganizationArtifactReport(
oar.organization,
oar.name,
oar.modules map { mr =>
ModuleReport(
mr.module,
mr.artifacts,
mr.missingArtifacts,
mr.status,
mr.publicationDate,
mr.resolver,
mr.artifactResolver,
mr.evicted,
mr.evictedData,
mr.evictedReason,
mr.problem,
mr.homepage,
mr.extraAttributes,
mr.isDefault,
mr.branch,
mr.configurations,
mr.licenses,
filterOutArtificialCallers(mr.callers)
)
}
)
cr.details map { oar =>
OrganizationArtifactReport(
oar.organization,
oar.name,
oar.modules map { mr =>
ModuleReport(
mr.module,
mr.artifacts,
mr.missingArtifacts,
mr.status,
mr.publicationDate,
mr.resolver,
mr.artifactResolver,
mr.evicted,
mr.evictedData,
mr.evictedReason,
mr.problem,
mr.homepage,
mr.extraAttributes,
mr.isDefault,
mr.branch,
mr.configurations,
mr.licenses,
filterOutArtificialCallers(mr.callers)
)
}
)
}
)
})

View File

@ -58,8 +58,8 @@ private[librarymanagement] abstract class SemComparatorExtra {
protected def toStringImpl: String = {
val versionStr = Seq(major, minor, patch)
.collect {
case Some(v) => v.toString
.collect { case Some(v) =>
v.toString
}
.mkString(".")
val tagsStr = if (tags.nonEmpty) s"-${tags.mkString("-")}" else ""
@ -177,8 +177,8 @@ private[librarymanagement] abstract class SemComparatorFunctions {
}
parse(
numbers
.collect {
case Some(v) => v.toString
.collect { case Some(v) =>
v.toString
}
.mkString(".")
)

View File

@ -71,7 +71,7 @@ object VersionRange {
case _: NumberFormatException =>
// TODO - if the version doesn't meet our expectations, maybe we just issue a hard
// error instead of softly ignoring the attempt to rewrite.
//sys.error(s"Could not fix version [$revision] into maven style version")
// sys.error(s"Could not fix version [$revision] into maven style version")
revision
}
}

View File

@ -36,7 +36,8 @@ private[sbt] object VersionSchemes {
case x => sys.error(s"unknown version scheme: $x")
}
/** info.versionScheme property will be included into POM after sbt 1.4.0.
/**
* info.versionScheme property will be included into POM after sbt 1.4.0.
*/
def extractFromId(mid: ModuleID): Option[String] = extractFromExtraAttributes(mid.extraAttributes)

View File

@ -27,7 +27,8 @@ object CrossVersionUtil {
private[sbt] val BinCompatV = raw"""$basicVersion(-$tagPattern)?-bin(-.*)?""".r
private val CandidateV = raw"""$basicVersion(-RC\d+)""".r
private val MilestonV = raw"""$basicVersion(-M$tagPattern)""".r
private val NonReleaseV_n = raw"""$basicVersion((?:-$tagPattern)*)""".r // 0-n word suffixes, with leading dashes
private val NonReleaseV_n =
raw"""$basicVersion((?:-$tagPattern)*)""".r // 0-n word suffixes, with leading dashes
private val NonReleaseV_1 = raw"""$basicVersion(-$tagPattern)""".r // 1 word suffix, after a dash
private[sbt] val PartialVersion = raw"""($longPattern)\.($longPattern)(?:\..+)?""".r

View File

@ -37,13 +37,13 @@ private[librarymanagement] abstract class CrossVersionFunctions {
*/
def fullWith(prefix: String, suffix: String): CrossVersion = Full(prefix, suffix)
/** Cross-versions a module with the binary version (typically the binary Scala version). */
/** Cross-versions a module with the binary version (typically the binary Scala version). */
def binary: CrossVersion = Binary()
/** Disables cross versioning for a module. */
def disabled: CrossVersion = sbt.librarymanagement.Disabled
/** Cross-versions a module with a constant string (typically the binary Scala version). */
/** Cross-versions a module with a constant string (typically the binary Scala version). */
def constant(value: String): CrossVersion = Constant(value)
/**
@ -218,7 +218,7 @@ private[librarymanagement] abstract class CrossVersionFunctions {
*/
def scalaApiVersion(v: String): Option[(Long, Long)] = CrossVersionUtil.scalaApiVersion(v)
/** Regular expression that extracts the major and minor components of a version into matched groups 1 and 2.*/
/** Regular expression that extracts the major and minor components of a version into matched groups 1 and 2. */
val PartialVersion = CrossVersionUtil.PartialVersion
/** Extracts the major and minor components of a version string `s` or returns `None` if the version is improperly formatted. */

View File

@ -29,7 +29,9 @@ trait DependencyFilterExtra {
): ArtifactFilter =
new ArtifactFilter {
def apply(a: Artifact): Boolean =
name.accept(a.name) && `type`.accept(a.`type`) && extension.accept(a.extension) && classifier
name.accept(a.name) && `type`.accept(a.`type`) && extension.accept(
a.extension
) && classifier
.accept(a.classifier getOrElse "")
}

View File

@ -189,10 +189,9 @@ class DependencyResolution private[sbt] (lmEngine: DependencyResolutionInterface
((sourceArtifactTypes.toIterable map (_ -> Artifact.SourceClassifier))
:: (docArtifactTypes.toIterable map (_ -> Artifact.DocClassifier)) :: Nil).flatten.toMap
Right(r.substitute { (conf, mid, artFileSeq) =>
artFileSeq map {
case (art, f) =>
// Deduce the classifier from the type if no classifier is present already
art.withClassifier(art.classifier orElse typeClassifierMap.get(art.`type`)) -> f
artFileSeq map { case (art, f) =>
// Deduce the classifier from the type if no classifier is present already
art.withClassifier(art.classifier orElse typeClassifierMap.get(art.`type`)) -> f
}
})
case Left(w) => Left(w)
@ -200,10 +199,9 @@ class DependencyResolution private[sbt] (lmEngine: DependencyResolutionInterface
}
protected def directDependenciesNames(module: ModuleDescriptor): String =
(module.directDependencies map {
case mID: ModuleID =>
import mID._
s"$organization % $name % $revision"
(module.directDependencies map { case mID: ModuleID =>
import mID._
s"$organization % $name % $revision"
}).mkString(", ")
}

View File

@ -106,11 +106,16 @@ object EvictionError {
if (isNameScalaSuffixed(p.name)) assumedVersionScheme
else assumedVersionSchemeJava
val guess = VersionSchemes.evalFunc(scheme)
(p.evicteds forall { r =>
f((r.module, winnerOpt, module.scalaModuleInfo))
}, schemeOpt.getOrElse("?"), p.evicteds forall { r =>
guess((r.module, winnerOpt, module.scalaModuleInfo))
}, scheme)
(
p.evicteds forall { r =>
f((r.module, winnerOpt, module.scalaModuleInfo))
},
schemeOpt.getOrElse("?"),
p.evicteds forall { r =>
guess((r.module, winnerOpt, module.scalaModuleInfo))
},
scheme
)
}
pairs foreach {
// don't report on a transitive eviction that does not have a winner
@ -152,30 +157,29 @@ final class EvictionError private[sbt] (
val out: mutable.ListBuffer[String] = mutable.ListBuffer()
out += "found version conflict(s) in library dependencies; some are suspected to be binary incompatible:"
out += ""
evictions.foreach({
case (a, scheme) =>
val revs = a.evicteds map { _.module.revision }
val revsStr =
if (revs.size <= 1) revs.mkString else "{" + revs.distinct.mkString(", ") + "}"
val seen: mutable.Set[ModuleID] = mutable.Set()
val callers: List[String] = (a.evicteds.toList ::: a.winner.toList) flatMap { r =>
val rev = r.module.revision
r.callers.toList flatMap { caller =>
if (seen(caller.caller)) Nil
else {
seen += caller.caller
List(f"\t +- ${caller}%-50s (depends on $rev)")
}
evictions.foreach({ case (a, scheme) =>
val revs = a.evicteds map { _.module.revision }
val revsStr =
if (revs.size <= 1) revs.mkString else "{" + revs.distinct.mkString(", ") + "}"
val seen: mutable.Set[ModuleID] = mutable.Set()
val callers: List[String] = (a.evicteds.toList ::: a.winner.toList) flatMap { r =>
val rev = r.module.revision
r.callers.toList flatMap { caller =>
if (seen(caller.caller)) Nil
else {
seen += caller.caller
List(f"\t +- ${caller}%-50s (depends on $rev)")
}
}
val que = if (assumed) "?" else ""
val winnerRev = a.winner match {
case Some(r) => s":${r.module.revision} ($scheme$que) is selected over ${revsStr}"
case _ => " is evicted for all versions"
}
val title = s"\t* ${a.organization}:${a.name}$winnerRev"
val lines = title :: (if (a.showCallers) callers.reverse else Nil) ::: List("")
out ++= lines
}
val que = if (assumed) "?" else ""
val winnerRev = a.winner match {
case Some(r) => s":${r.module.revision} ($scheme$que) is selected over ${revsStr}"
case _ => " is evicted for all versions"
}
val title = s"\t* ${a.organization}:${a.name}$winnerRev"
val lines = title :: (if (a.showCallers) callers.reverse else Nil) ::: List("")
out ++= lines
})
out.toList
}

View File

@ -279,10 +279,12 @@ object EvictionWarning {
}
confs flatMap { confReport =>
confReport.details map { detail =>
if ((detail.modules exists { _.evicted }) &&
!(buffer exists { x =>
(x.organization == detail.organization) && (x.name == detail.name)
})) {
if (
(detail.modules exists { _.evicted }) &&
!(buffer exists { x =>
(x.organization == detail.organization) && (x.name == detail.name)
})
) {
buffer += detail
}
}

View File

@ -37,10 +37,10 @@ private[librarymanagement] abstract class ModuleIDExtra {
protected def toStringImpl: String =
s"""$organization:$name:$revision""" +
(configurations match { case Some(s) => ":" + s; case None => "" }) + {
val attr = attributeString
if (attr == "") ""
else " " + attr
} +
val attr = attributeString
if (attr == "") ""
else " " + attr
} +
(if (extraAttributes.isEmpty) "" else " " + extraString)
protected def attributeString: String = {
@ -95,10 +95,10 @@ private[librarymanagement] abstract class ModuleIDExtra {
})
// () required for chaining
/** Do not follow dependencies of this module. Synonym for `intransitive`.*/
/** Do not follow dependencies of this module. Synonym for `intransitive`. */
def notTransitive(): ModuleID = intransitive()
/** Do not follow dependencies of this module. Synonym for `notTransitive`.*/
/** Do not follow dependencies of this module. Synonym for `notTransitive`. */
def intransitive(): ModuleID = withIsTransitive(false)
/**

View File

@ -167,7 +167,7 @@ private[librarymanagement] abstract class ResolverFunctions {
)
def jcenterRepo = JCenterRepository
/** Add the local and Maven Central repositories to the user repositories. */
/** Add the local and Maven Central repositories to the user repositories. */
def combineDefaultResolvers(userResolvers: Vector[Resolver]): Vector[Resolver] =
combineDefaultResolvers(userResolvers, mavenCentral = true)
@ -214,7 +214,10 @@ private[librarymanagement] abstract class ResolverFunctions {
single(JCenterRepository, jcenter) ++
(xs.partition(_ == DefaultMavenRepository) match {
case (_, xs) =>
single(DefaultMavenRepository, mavenCentral) ++ xs // TODO - Do we need to filter out duplicates?
single(
DefaultMavenRepository,
mavenCentral
) ++ xs // TODO - Do we need to filter out duplicates?
})
})
}
@ -222,7 +225,7 @@ private[librarymanagement] abstract class ResolverFunctions {
private def single[T](value: T, nonEmpty: Boolean): Vector[T] =
if (nonEmpty) Vector(value) else Vector.empty
/** A base class for defining factories for interfaces to Ivy repositories that require a hostname , port, and patterns. */
/** A base class for defining factories for interfaces to Ivy repositories that require a hostname , port, and patterns. */
sealed abstract class Define[RepositoryType <: SshBasedRepository] {
/** Subclasses should implement this method to */
@ -251,8 +254,8 @@ private[librarymanagement] abstract class ResolverFunctions {
* patterns will be resolved. `basePatterns` are the initial patterns to use.
* A ManagedProject has an implicit defining these initial patterns based on a setting for either Maven or Ivy style patterns.
*/
def apply(name: String, hostname: String, basePath: String)(
implicit basePatterns: Patterns
def apply(name: String, hostname: String, basePath: String)(implicit
basePatterns: Patterns
): RepositoryType =
apply(name, Some(hostname), None, Some(basePath))
@ -260,8 +263,8 @@ private[librarymanagement] abstract class ResolverFunctions {
* Constructs this repository type with the given `name`, `hostname`, and `port`. `basePatterns` are the initial patterns to use.
* A ManagedProject has an implicit defining these initial patterns based on a setting for either Maven or Ivy style patterns.
*/
def apply(name: String, hostname: String, port: Int)(
implicit basePatterns: Patterns
def apply(name: String, hostname: String, port: Int)(implicit
basePatterns: Patterns
): RepositoryType =
apply(name, Some(hostname), Some(port), None)
@ -270,8 +273,8 @@ private[librarymanagement] abstract class ResolverFunctions {
* patterns will be resolved. `basePatterns` are the initial patterns to use.
* A ManagedProject has an implicit defining these initial patterns based on a setting for either Maven or Ivy style patterns.
*/
def apply(name: String, hostname: String, port: Int, basePath: String)(
implicit basePatterns: Patterns
def apply(name: String, hostname: String, port: Int, basePath: String)(implicit
basePatterns: Patterns
): RepositoryType =
apply(name, Some(hostname), Some(port), Some(basePath))
@ -286,13 +289,13 @@ private[librarymanagement] abstract class ResolverFunctions {
construct(name, SshConnection(None, hostname, port), resolvePatterns(basePath, basePatterns))
}
/** A factory to construct an interface to an Ivy SSH resolver.*/
/** A factory to construct an interface to an Ivy SSH resolver. */
object ssh extends Define[SshRepository] {
protected def construct(name: String, connection: SshConnection, patterns: Patterns) =
SshRepository(name, connection, patterns, None)
}
/** A factory to construct an interface to an Ivy SFTP resolver.*/
/** A factory to construct an interface to an Ivy SFTP resolver. */
object sftp extends Define[SftpRepository] {
protected def construct(name: String, connection: SshConnection, patterns: Patterns) =
SftpRepository(name, connection, patterns)
@ -330,8 +333,8 @@ private[librarymanagement] abstract class ResolverFunctions {
def apply(name: String, baseURL: URL)(implicit basePatterns: Patterns): URLRepository =
baseRepository(baseURL.toURI.normalize.toString)(URLRepository(name, _))
}
private def baseRepository[T](base: String)(construct: Patterns => T)(
implicit basePatterns: Patterns
private def baseRepository[T](base: String)(construct: Patterns => T)(implicit
basePatterns: Patterns
): T =
construct(resolvePatterns(base, basePatterns))
@ -363,7 +366,7 @@ private[librarymanagement] abstract class ResolverFunctions {
}
def defaultFileConfiguration = FileConfiguration(true, None)
def mavenStylePatterns = Patterns().withArtifactPatterns(Vector(mavenStyleBasePattern))
def ivyStylePatterns = defaultIvyPatterns //Patterns(Nil, Nil, false)
def ivyStylePatterns = defaultIvyPatterns // Patterns(Nil, Nil, false)
def defaultPatterns = mavenStylePatterns
def mavenStyleBasePattern =
@ -394,7 +397,9 @@ private[librarymanagement] abstract class ResolverFunctions {
}
sys.props.get("maven.repo.local").map(new File(_)) orElse
loadHomeFromSettings(() => new File(sbt.io.Path.userHome, ".m2/settings.xml")) orElse
loadHomeFromSettings(() => new File(new File(System.getenv("M2_HOME")), "conf/settings.xml")) getOrElse
loadHomeFromSettings(() =>
new File(new File(System.getenv("M2_HOME")), "conf/settings.xml")
) getOrElse
new File(sbt.io.Path.userHome, ".m2/repository")
}
// TODO - should this just be the *exact* same as mavenLocal? probably...

View File

@ -12,16 +12,15 @@ final class RichUpdateReport(report: UpdateReport) {
private[sbt] def recomputeStamps(): UpdateReport = {
val files = report.cachedDescriptor +: allFiles
val stamps = files
.map(
f =>
(
f,
// TODO: The list of files may also contain some odd files that do not actually exist like:
// "./target/ivyhome/resolution-cache/com.example/foo/0.4.0/resolved.xml.xml".
// IO.getModifiedTimeOrZero() will just return zero, but the list of files should not contain such
// files to begin with, in principle.
IO.getModifiedTimeOrZero(f)
)
.map(f =>
(
f,
// TODO: The list of files may also contain some odd files that do not actually exist like:
// "./target/ivyhome/resolution-cache/com.example/foo/0.4.0/resolved.xml.xml".
// IO.getModifiedTimeOrZero() will just return zero, but the list of files should not contain such
// files to begin with, in principle.
IO.getModifiedTimeOrZero(f)
)
)
.toMap
UpdateReport(report.cachedDescriptor, report.configurations, report.stats, stamps)
@ -65,13 +64,13 @@ final class RichUpdateReport(report: UpdateReport) {
file
}
/** Constructs a new report that only contains files matching the specified filter.*/
/** Constructs a new report that only contains files matching the specified filter. */
def filter(f: DependencyFilter): UpdateReport =
moduleReportMap { (configuration, modReport) =>
modReport
.withArtifacts(
modReport.artifacts filter {
case (art, _) => f(configuration, modReport.module, art)
modReport.artifacts filter { case (art, _) =>
f(configuration, modReport.module, art)
}
)
.withMissingArtifacts(

View File

@ -10,9 +10,13 @@ final class ResolveException(
val failedPaths: Map[ModuleID, Seq[ModuleID]]
) extends RuntimeException(messages.mkString("\n")) {
def this(messages: Seq[String], failed: Seq[ModuleID]) =
this(messages, failed, Map(failed map { m =>
m -> Nil
}: _*))
this(
messages,
failed,
Map(failed map { m =>
m -> Nil
}: _*)
)
}
/**
@ -30,13 +34,12 @@ object UnresolvedWarning {
config: UnresolvedWarningConfiguration
): UnresolvedWarning = {
def modulePosition(m0: ModuleID): Option[SourcePosition] =
config.modulePositions.find {
case (m, _) =>
(m.organization == m0.organization) &&
(m0.name startsWith m.name) &&
(m.revision == m0.revision)
} map {
case (_, p) => p
config.modulePositions.find { case (m, _) =>
(m.organization == m0.organization) &&
(m0.name startsWith m.name) &&
(m.revision == m0.revision)
} map { case (_, p) =>
p
}
val failedPaths = err.failed map { (x: ModuleID) =>
err.failedPaths(x).toList.reverse map { id =>
@ -67,9 +70,8 @@ object UnresolvedWarning {
if (path.nonEmpty) {
val head = path.head
buffer += "\t\t" + head._1.toString + sourcePosStr(head._2)
path.tail foreach {
case (m, pos) =>
buffer += "\t\t +- " + m.toString + sourcePosStr(pos)
path.tail foreach { case (m, pos) =>
buffer += "\t\t +- " + m.toString + sourcePosStr(pos)
}
}
}

View File

@ -29,9 +29,13 @@ private[librarymanagement] abstract class ConfigurationReportExtra {
}
def retrieve(f: (ConfigRef, ModuleID, Artifact, File) => File): ConfigurationReport =
ConfigurationReport(configuration, modules map {
_.retrieve((mid, art, file) => f(configuration, mid, art, file))
}, details)
ConfigurationReport(
configuration,
modules map {
_.retrieve((mid, art, file) => f(configuration, mid, art, file))
},
details
)
}
private[librarymanagement] abstract class ModuleReportExtra {
@ -124,24 +128,23 @@ private[librarymanagement] abstract class UpdateReportExtra {
/** All resolved modules in all configurations. */
def allModules: Vector[ModuleID] = {
val key = (m: ModuleID) => (m.organization, m.name, m.revision)
configurations.flatMap(_.allModules).groupBy(key).toVector map {
case (_, v) =>
v reduceLeft { (agg, x) =>
agg.withConfigurations(
(agg.configurations, x.configurations) match {
case (None, _) => x.configurations
case (Some(ac), None) => Some(ac)
case (Some(ac), Some(xc)) => Some(s"$ac;$xc")
}
)
}
configurations.flatMap(_.allModules).groupBy(key).toVector map { case (_, v) =>
v reduceLeft { (agg, x) =>
agg.withConfigurations(
(agg.configurations, x.configurations) match {
case (None, _) => x.configurations
case (Some(ac), None) => Some(ac)
case (Some(ac), Some(xc)) => Some(s"$ac;$xc")
}
)
}
}
}
def retrieve(f: (ConfigRef, ModuleID, Artifact, File) => File): UpdateReport =
UpdateReport(cachedDescriptor, configurations map { _ retrieve f }, stats, stamps)
/** Gets the report for the given configuration, or `None` if the configuration was not resolved.*/
/** Gets the report for the given configuration, or `None` if the configuration was not resolved. */
def configuration(s: ConfigRef) = configurations.find(_.configuration == s)
/** Gets the names of all resolved configurations. This `UpdateReport` contains one `ConfigurationReport` for each configuration in this list. */

View File

@ -162,7 +162,8 @@ object VersionNumber {
}
}
/** A variant of SemVar that seems to be common among the Scala libraries.
/**
* A variant of SemVar that seems to be common among the Scala libraries.
* The second segment (y in x.y.z) increments breaks the binary compatibility even when x > 0.
* Also API compatibility is expected even when the first segment is zero.
*/
@ -172,7 +173,8 @@ object VersionNumber {
PackVer.isCompatible(v1, v2)
}
/** A variant of SemVar that seems to be common among the Scala libraries.
/**
* A variant of SemVar that seems to be common among the Scala libraries.
* The second segment (y in x.y.z) increments breaks the binary compatibility even when x > 0.
* Also API compatibility is expected even when the first segment is zero.
*/
@ -193,7 +195,8 @@ object VersionNumber {
}
}
/** A variant of SemVar that enforces API compatibility when the first segment is zero.
/**
* A variant of SemVar that enforces API compatibility when the first segment is zero.
*/
object EarlySemVer extends VersionNumberCompatibility {
import SemVer._

View File

@ -21,8 +21,6 @@ import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
*
* Also see: http://ant.apache.org/ivy/history/2.3.0/ivyfile/dependency.html
* and: http://svn.apache.org/repos/asf/ant/ivy/core/tags/2.3.0/src/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorBuilder.java
*
*
*/
object ReplaceMavenConfigurationMappings {

View File

@ -56,7 +56,7 @@ class ComponentManager(
/** This is used to lock the local cache in project/boot/. By checking the local cache first, we can avoid grabbing a global lock. */
private def lockLocalCache[T](action: => T): T = lock(provider.lockFile)(action)
/** This is used to ensure atomic access to components in the global Ivy cache.*/
/** This is used to ensure atomic access to components in the global Ivy cache. */
private def lockGlobalCache[T](action: => T): T = lock(ivyCache.lockFile)(action)
private def lock[T](file: File)(action: => T): T =
globalLock(file, new Callable[T] { def call = action })

View File

@ -151,83 +151,82 @@ private[sbt] object ConvertResolver {
(updateOptions.resolverConverter orElse defaultConvert)((r, settings, log))
/** The default implementation of converter. */
lazy val defaultConvert: ResolverConverter = {
case (r, settings, log) =>
val managedChecksums = Option(settings.getVariable(ManagedChecksums)) match {
case Some(x) => x.toBoolean
case _ => false
lazy val defaultConvert: ResolverConverter = { case (r, settings, log) =>
val managedChecksums = Option(settings.getVariable(ManagedChecksums)) match {
case Some(x) => x.toBoolean
case _ => false
}
r match {
case repo: MavenRepository => {
val pattern = Collections.singletonList(
Resolver.resolvePattern(repo.root, Resolver.mavenStyleBasePattern)
)
final class PluginCapableResolver
extends IBiblioResolver
with ChecksumFriendlyURLResolver
with DescriptorRequired {
override val managedChecksumsEnabled: Boolean = managedChecksums
override def getResource(resource: Resource, dest: File): Long = get(resource, dest)
def setPatterns(): Unit = {
// done this way for access to protected methods.
setArtifactPatterns(pattern)
setIvyPatterns(pattern)
}
}
val resolver = new PluginCapableResolver
if (repo.localIfFile) resolver.setRepository(new LocalIfFileRepo)
initializeMavenStyle(resolver, repo.name, repo.root)
resolver
.setPatterns() // has to be done after initializeMavenStyle, which calls methods that overwrite the patterns
resolver
}
r match {
case repo: MavenRepository => {
val pattern = Collections.singletonList(
Resolver.resolvePattern(repo.root, Resolver.mavenStyleBasePattern)
)
final class PluginCapableResolver
extends IBiblioResolver
with ChecksumFriendlyURLResolver
with DescriptorRequired {
override val managedChecksumsEnabled: Boolean = managedChecksums
override def getResource(resource: Resource, dest: File): Long = get(resource, dest)
def setPatterns(): Unit = {
// done this way for access to protected methods.
setArtifactPatterns(pattern)
setIvyPatterns(pattern)
}
}
val resolver = new PluginCapableResolver
if (repo.localIfFile) resolver.setRepository(new LocalIfFileRepo)
initializeMavenStyle(resolver, repo.name, repo.root)
resolver
.setPatterns() // has to be done after initializeMavenStyle, which calls methods that overwrite the patterns
resolver
case repo: SshRepository => {
val resolver = new SshResolver with DescriptorRequired with ThreadSafeSshBasedResolver {
override val managedChecksumsEnabled: Boolean = managedChecksums
override def getResource(resource: Resource, dest: File): Long = get(resource, dest)
}
case repo: SshRepository => {
val resolver = new SshResolver with DescriptorRequired with ThreadSafeSshBasedResolver {
override val managedChecksumsEnabled: Boolean = managedChecksums
override def getResource(resource: Resource, dest: File): Long = get(resource, dest)
}
initializeSSHResolver(resolver, repo, settings)
repo.publishPermissions.foreach(perm => resolver.setPublishPermissions(perm))
resolver
}
case repo: SftpRepository => {
val resolver = new SFTPResolver with ThreadSafeSshBasedResolver
initializeSSHResolver(resolver, repo, settings)
resolver
}
case repo: FileRepository => {
val resolver = new FileSystemResolver with DescriptorRequired {
// Workaround for #1156
// Temporarily in sbt 0.13.x we deprecate overwriting
// in local files for non-changing revisions.
// This will be fully enforced in sbt 1.0.
setRepository(new WarnOnOverwriteFileRepo())
override val managedChecksumsEnabled: Boolean = managedChecksums
override def getResource(resource: Resource, dest: File): Long = get(resource, dest)
}
resolver.setName(repo.name)
initializePatterns(resolver, repo.patterns, settings)
import repo.configuration.{ isLocal, isTransactional }
resolver.setLocal(isLocal)
isTransactional.foreach(value => resolver.setTransactional(value.toString))
resolver
}
case repo: URLRepository => {
val resolver = new URLResolver with ChecksumFriendlyURLResolver with DescriptorRequired {
override val managedChecksumsEnabled: Boolean = managedChecksums
override def getResource(resource: Resource, dest: File): Long = get(resource, dest)
}
resolver.setName(repo.name)
initializePatterns(resolver, repo.patterns, settings)
resolver
}
case repo: ChainedResolver =>
IvySbt.resolverChain(repo.name, repo.resolvers, settings, log)
case repo: RawRepository =>
repo.resolver match {
case r: DependencyResolver => r
}
initializeSSHResolver(resolver, repo, settings)
repo.publishPermissions.foreach(perm => resolver.setPublishPermissions(perm))
resolver
}
case repo: SftpRepository => {
val resolver = new SFTPResolver with ThreadSafeSshBasedResolver
initializeSSHResolver(resolver, repo, settings)
resolver
}
case repo: FileRepository => {
val resolver = new FileSystemResolver with DescriptorRequired {
// Workaround for #1156
// Temporarily in sbt 0.13.x we deprecate overwriting
// in local files for non-changing revisions.
// This will be fully enforced in sbt 1.0.
setRepository(new WarnOnOverwriteFileRepo())
override val managedChecksumsEnabled: Boolean = managedChecksums
override def getResource(resource: Resource, dest: File): Long = get(resource, dest)
}
resolver.setName(repo.name)
initializePatterns(resolver, repo.patterns, settings)
import repo.configuration.{ isLocal, isTransactional }
resolver.setLocal(isLocal)
isTransactional.foreach(value => resolver.setTransactional(value.toString))
resolver
}
case repo: URLRepository => {
val resolver = new URLResolver with ChecksumFriendlyURLResolver with DescriptorRequired {
override val managedChecksumsEnabled: Boolean = managedChecksums
override def getResource(resource: Resource, dest: File): Long = get(resource, dest)
}
resolver.setName(repo.name)
initializePatterns(resolver, repo.patterns, settings)
resolver
}
case repo: ChainedResolver =>
IvySbt.resolverChain(repo.name, repo.resolvers, settings, log)
case repo: RawRepository =>
repo.resolver match {
case r: DependencyResolver => r
}
}
}
private sealed trait DescriptorRequired extends BasicResolver {
@ -290,8 +289,9 @@ private[sbt] object ConvertResolver {
override def getDependency(dd: DependencyDescriptor, data: ResolveData) = {
val prev = descriptorString(isAllownomd)
setDescriptor(descriptorString(hasExplicitURL(dd)))
val t = try super.getDependency(dd, data)
finally setDescriptor(prev)
val t =
try super.getDependency(dd, data)
finally setDescriptor(prev)
t
}
def descriptorString(optional: Boolean) =

View File

@ -64,7 +64,7 @@ object CustomPomParser {
// Evil hackery to override the default maven pom mappings.
ReplaceMavenConfigurationMappings.init()
/** The key prefix that indicates that this is used only to store extra information and is not intended for dependency resolution.*/
/** The key prefix that indicates that this is used only to store extra information and is not intended for dependency resolution. */
val InfoKeyPrefix = SbtPomExtraProperties.POM_INFO_KEY_PREFIX
val ApiURLKey = SbtPomExtraProperties.POM_API_KEY
val VersionSchemeKey = SbtPomExtraProperties.VERSION_SCHEME_KEY
@ -109,7 +109,9 @@ object CustomPomParser {
val MyHash = MakeTransformHash(md)
// sbt 0.13.1 used "sbtTransformHash" instead of "e:sbtTransformHash" until #1192 so read both
Option(extraInfo).isDefined &&
((Option(extraInfo get TransformedHashKey) orElse Option(extraInfo get oldTransformedHashKey)) match {
((Option(extraInfo get TransformedHashKey) orElse Option(
extraInfo get oldTransformedHashKey
)) match {
case Some(MyHash) => true
case _ => false
})
@ -269,17 +271,23 @@ object CustomPomParser {
for (l <- md.getLicenses) dmd.addLicense(l)
for ((key, value) <- md.getExtraInfo.asInstanceOf[java.util.Map[String, String]].asScala)
dmd.addExtraInfo(key, value)
dmd.addExtraInfo(TransformedHashKey, MakeTransformHash(md)) // mark as transformed by this version, so we don't need to do it again
for ((key, value) <- md.getExtraAttributesNamespaces
.asInstanceOf[java.util.Map[String, String]]
.asScala) dmd.addExtraAttributeNamespace(key, value)
dmd.addExtraInfo(
TransformedHashKey,
MakeTransformHash(md)
) // mark as transformed by this version, so we don't need to do it again
for (
(key, value) <- md.getExtraAttributesNamespaces
.asInstanceOf[java.util.Map[String, String]]
.asScala
) dmd.addExtraAttributeNamespace(key, value)
IvySbt.addExtraNamespace(dmd)
val withExtra = md.getDependencies map { dd =>
addExtra(dd, dependencyExtra)
}
val withVersionRangeMod: Seq[DependencyDescriptor] =
if (LMSysProp.modifyVersionRange) withExtra map { stripVersionRange } else withExtra
if (LMSysProp.modifyVersionRange) withExtra map { stripVersionRange }
else withExtra
val unique = IvySbt.mergeDuplicateDefinitions(withVersionRangeMod)
unique foreach dmd.addDependency

View File

@ -15,7 +15,7 @@ import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser
import org.apache.ivy.plugins.repository.Resource
import org.apache.ivy.plugins.repository.url.URLResource
/** Subclasses the default Ivy file parser in order to provide access to protected methods.*/
/** Subclasses the default Ivy file parser in order to provide access to protected methods. */
private[sbt] object CustomXmlParser extends XmlModuleDescriptorParser {
import XmlModuleDescriptorParser.Parser
class CustomParser(settings: IvySettings, defaultConfig: Option[String])
@ -26,7 +26,7 @@ private[sbt] object CustomXmlParser extends XmlModuleDescriptorParser {
}
def setInput(bytes: Array[Byte]): Unit = setInput(new ByteArrayInputStream(bytes))
/** Overridden because the super implementation overwrites the module descriptor.*/
/** Overridden because the super implementation overwrites the module descriptor. */
override def setResource(res: Resource): Unit = ()
override def setMd(md: DefaultModuleDescriptor) = {
super.setMd(md)

View File

@ -178,8 +178,8 @@ private[sbt] class FakeResolver(private var name: String, cacheDir: File, module
val artifact =
for {
artifacts <- modules get ((moduleOrganisation, moduleName, moduleRevision))
artifact <- artifacts find (
a => a.name == art.getName && a.tpe == art.getType && a.ext == art.getExt
artifact <- artifacts find (a =>
a.name == art.getName && a.tpe == art.getType && a.ext == art.getExt
)
} yield new ArtifactOrigin(art, /* isLocal = */ true, artifact.file.toURI.toURL.toString)

View File

@ -29,7 +29,7 @@ import sbt.internal.librarymanagement.IvyUtil.TransientNetworkException
object IvyActions {
/** Installs the dependencies of the given 'module' from the resolver named 'from' to the resolver named 'to'.*/
/** Installs the dependencies of the given 'module' from the resolver named 'from' to the resolver named 'to'. */
def install(module: IvySbt#Module, from: String, to: String, log: Logger): Unit = {
module.withModule(log) { (ivy, md, _) =>
for (dependency <- md.getDependencies) {
@ -57,7 +57,7 @@ object IvyActions {
module.owner.cleanCachedResolutionCache()
}
/** Creates a Maven pom from the given Ivy configuration*/
/** Creates a Maven pom from the given Ivy configuration */
def makePomFile(module: IvySbt#Module, configuration: MakePomConfiguration, log: Logger): File = {
import configuration.{
allRepositories,
@ -91,13 +91,12 @@ object IvyActions {
val deliverIvyPattern = configuration.deliverIvyPattern
.getOrElse(sys.error("deliverIvyPattern must be specified."))
val status = getDeliverStatus(configuration.status)
module.withModule(log) {
case (ivy, md, _) =>
val revID = md.getModuleRevisionId
val options = DeliverOptions.newInstance(ivy.getSettings).setStatus(status)
options.setConfs(getConfigurations(md, configuration.configurations))
ivy.deliver(revID, revID.getRevision, deliverIvyPattern, options)
deliveredFile(ivy, deliverIvyPattern, md)
module.withModule(log) { case (ivy, md, _) =>
val revID = md.getModuleRevisionId
val options = DeliverOptions.newInstance(ivy.getSettings).setStatus(status)
options.setConfs(getConfigurations(md, configuration.configurations))
ivy.deliver(revID, revID.getRevision, deliverIvyPattern, options)
deliveredFile(ivy, deliverIvyPattern, md)
}
}
@ -130,18 +129,17 @@ object IvyActions {
val artifacts = Map(configuration.artifacts: _*)
val checksums = configuration.checksums
module.withModule(log) {
case (ivy, md, _) =>
val resolver = ivy.getSettings.getResolver(resolverName)
if (resolver eq null) sys.error("Undefined resolver '" + resolverName + "'")
val ivyArtifact = ivyFile map { file =>
(MDArtifact.newIvyArtifact(md), file)
}
val cross = crossVersionMap(module.moduleSettings)
val as = mapArtifacts(md, cross, artifacts) ++ ivyArtifact.toList
withChecksums(resolver, checksums) {
publish(md, as, resolver, overwrite = configuration.overwrite)
}
module.withModule(log) { case (ivy, md, _) =>
val resolver = ivy.getSettings.getResolver(resolverName)
if (resolver eq null) sys.error("Undefined resolver '" + resolverName + "'")
val ivyArtifact = ivyFile map { file =>
(MDArtifact.newIvyArtifact(md), file)
}
val cross = crossVersionMap(module.moduleSettings)
val as = mapArtifacts(md, cross, artifacts) ++ ivyArtifact.toList
withChecksums(resolver, checksums) {
publish(md, as, resolver, overwrite = configuration.overwrite)
}
}
}
private[this] def withChecksums[T](resolver: DependencyResolver, checksums: Vector[String])(
@ -193,35 +191,36 @@ object IvyActions {
uwconfig: UnresolvedWarningConfiguration,
log: Logger
): Either[UnresolvedWarning, UpdateReport] = {
module.withModule(log) {
case (ivy, moduleDescriptor, _) =>
// Warn about duplicated and inconsistent dependencies
val iw = IvySbt.inconsistentDuplicateWarning(moduleDescriptor)
iw.foreach(log.warn(_))
module.withModule(log) { case (ivy, moduleDescriptor, _) =>
// Warn about duplicated and inconsistent dependencies
val iw = IvySbt.inconsistentDuplicateWarning(moduleDescriptor)
iw.foreach(log.warn(_))
val metadataDirectory = configuration.metadataDirectory
val metadataDirectory = configuration.metadataDirectory
// Create inputs, resolve and retrieve the module descriptor
val inputs = ResolutionInputs(ivy, moduleDescriptor, configuration, log)
val resolutionResult: Either[ResolveException, UpdateReport] = {
if (module.owner.configuration.updateOptions.cachedResolution && metadataDirectory.isDefined) {
val cache =
metadataDirectory.getOrElse(sys.error("Missing directory for cached resolution."))
cachedResolveAndRetrieve(inputs, cache)
} else resolveAndRetrieve(inputs)
}
// Create inputs, resolve and retrieve the module descriptor
val inputs = ResolutionInputs(ivy, moduleDescriptor, configuration, log)
val resolutionResult: Either[ResolveException, UpdateReport] = {
if (
module.owner.configuration.updateOptions.cachedResolution && metadataDirectory.isDefined
) {
val cache =
metadataDirectory.getOrElse(sys.error("Missing directory for cached resolution."))
cachedResolveAndRetrieve(inputs, cache)
} else resolveAndRetrieve(inputs)
}
// Convert to unresolved warning or retrieve update report
resolutionResult.fold(
exception => Left(UnresolvedWarning(exception, uwconfig)),
ur0 => {
val ur = configuration.retrieveManaged match {
case Some(retrieveConf) => retrieve(log, ivy, ur0, retrieveConf)
case _ => ur0
}
Right(ur)
// Convert to unresolved warning or retrieve update report
resolutionResult.fold(
exception => Left(UnresolvedWarning(exception, uwconfig)),
ur0 => {
val ur = configuration.retrieveManaged match {
case Some(retrieveConf) => retrieve(log, ivy, ur0, retrieveConf)
case _ => ur0
}
)
Right(ur)
}
)
}
}
@ -252,11 +251,10 @@ object IvyActions {
exclude.getOrElse(restrictedCopy(id, false), Set.empty[String])
def extractExcludes(report: UpdateReport): Map[ModuleID, Set[String]] =
report.allMissing flatMap {
case (_, mod, art) =>
art.classifier.map { c =>
(restrictedCopy(mod, false), c)
}
report.allMissing flatMap { case (_, mod, art) =>
art.classifier.map { c =>
(restrictedCopy(mod, false), c)
}
} groupBy (_._1) map { case (mod, pairs) => (mod, pairs.map(_._2).toSet) }
/**
@ -275,8 +273,8 @@ object IvyActions {
)
implicit def toIvyFilter(f: ArtifactTypeFilter): IvyFilter = new IvyFilter {
override def accept(o: Object): Boolean = Option(o) exists {
case a: IArtifact => applyFilter(a)
override def accept(o: Object): Boolean = Option(o) exists { case a: IArtifact =>
applyFilter(a)
}
def applyFilter(a: IArtifact): Boolean =
@ -498,13 +496,12 @@ object IvyActions {
checkFilesPresent(artifacts)
try {
resolver.beginPublishTransaction(module.getModuleRevisionId(), overwrite);
artifacts.foreach {
case (artifact, file) =>
IvyUtil.retryWithBackoff(
resolver.publish(artifact, file, overwrite),
TransientNetworkException.apply,
maxAttempts = LMSysProp.maxPublishAttempts
)
artifacts.foreach { case (artifact, file) =>
IvyUtil.retryWithBackoff(
resolver.publish(artifact, file, overwrite),
TransientNetworkException.apply,
maxAttempts = LMSysProp.maxPublishAttempts
)
}
resolver.commitPublishTransaction()
} catch {

View File

@ -31,11 +31,11 @@ private object NotInCache {
}
}
/** Provides methods for working at the level of a single jar file with the default Ivy cache.*/
/** Provides methods for working at the level of a single jar file with the default Ivy cache. */
class IvyCache(val ivyHome: Option[File]) {
def lockFile = new File(ivyHome getOrElse Path.userHome, ".sbt.cache.lock")
/** Caches the given 'file' with the given ID. It may be retrieved or cleared using this ID.*/
/** Caches the given 'file' with the given ID. It may be retrieved or cleared using this ID. */
def cacheJar(
moduleID: ModuleID,
file: File,
@ -52,7 +52,7 @@ class IvyCache(val ivyHome: Option[File]) {
}
}
/** Clears the cache of the jar for the given ID.*/
/** Clears the cache of the jar for the given ID. */
def clearCachedJar(id: ModuleID, lock: Option[xsbti.GlobalLock], log: Logger): Unit = {
try {
withCachedJar(id, lock, log)(_.delete); ()
@ -61,7 +61,7 @@ class IvyCache(val ivyHome: Option[File]) {
}
}
/** Copies the cached jar for the given ID to the directory 'toDirectory'. If the jar is not in the cache, NotInCache is thrown.*/
/** Copies the cached jar for the given ID to the directory 'toDirectory'. If the jar is not in the cache, NotInCache is thrown. */
def retrieveCachedJar(
id: ModuleID,
toDirectory: File,
@ -74,7 +74,7 @@ class IvyCache(val ivyHome: Option[File]) {
copyTo
}
/** Get the location of the cached jar for the given ID in the Ivy cache. If the jar is not in the cache, NotInCache is thrown .*/
/** Get the location of the cached jar for the given ID in the Ivy cache. If the jar is not in the cache, NotInCache is thrown . */
def withCachedJar[T](id: ModuleID, lock: Option[xsbti.GlobalLock], log: Logger)(
f: File => T
): T = {
@ -89,7 +89,7 @@ class IvyCache(val ivyHome: Option[File]) {
if (cachedFile.exists) f(cachedFile) else throw new NotInCache(id)
}
/** Calls the given function with the default Ivy cache.*/
/** Calls the given function with the default Ivy cache. */
def withDefaultCache[T](lock: Option[xsbti.GlobalLock], log: Logger)(
f: DefaultRepositoryCacheManager => T
): T = {
@ -103,7 +103,7 @@ class IvyCache(val ivyHome: Option[File]) {
}
private def unknownOrigin(artifact: IvyArtifact) = ArtifactOrigin.unkwnown(artifact)
/** A minimal Ivy setup with only a local resolver and the current directory as the base directory.*/
/** A minimal Ivy setup with only a local resolver and the current directory as the base directory. */
private def basicLocalIvy(lock: Option[xsbti.GlobalLock], log: Logger) = {
val local = Resolver.defaultLocal
val paths = IvyPaths(new File("."), ivyHome)
@ -115,12 +115,12 @@ class IvyCache(val ivyHome: Option[File]) {
(new IvySbt(conf, CustomHttp.defaultHttpClient), local)
}
/** Creates a default jar artifact based on the given ID.*/
/** Creates a default jar artifact based on the given ID. */
private def defaultArtifact(moduleID: ModuleID): IvyArtifact =
new DefaultArtifact(IvySbt.toID(moduleID), null, moduleID.name, "jar", "jar")
}
/** Required by Ivy for copying to the cache.*/
/** Required by Ivy for copying to the cache. */
private class FileDownloader extends ResourceDownloader {
def download(artifact: IvyArtifact, resource: Resource, dest: File): Unit = {
if (dest.exists()) dest.delete()

View File

@ -19,7 +19,7 @@ private[sbt] final class IvyLoggerInterface(logger: Logger) extends MessageLogge
case MSG_ERR => error(msg)
}
}
//DEBUG level messages are very verbose and rarely useful to users.
// DEBUG level messages are very verbose and rarely useful to users.
// TODO: provide access to this information some other way
def debug(msg: String): Unit = ()
def verbose(msg: String): Unit = logger.verbose(msg)

View File

@ -67,9 +67,11 @@ object IvyScalaUtil {
new NamespaceTransformer {
def transform(mrid: ModuleRevisionId): ModuleRevisionId = {
if (mrid == null) mrid
else if ((isScala2Artifact(mrid.getName) || isScala3Artifact(mrid.getName)) &&
configQualifies &&
dependeeQualifies) {
else if (
(isScala2Artifact(mrid.getName) || isScala3Artifact(mrid.getName)) &&
configQualifies &&
dependeeQualifies
) {
// do not override the binary incompatible Scala version because:
// - the artifacts compiled with Scala 3 depends on the Scala 2.13 scala-library
// - the Scala 2 TASTy reader can consume the Scala 3 artifacts
@ -152,7 +154,8 @@ object IvyScalaUtil {
.forall(bv => bv.startsWith("3") || bv.startsWith("2.13"))
def matchesOneOfTheConfigs = dep.getModuleConfigurations exists { scalaVersionConfigs }
val mismatched = isScalaLangOrg && isScalaArtifact && hasBinVerMismatch && matchesOneOfTheConfigs
val mismatched =
isScalaLangOrg && isScalaArtifact && hasBinVerMismatch && matchesOneOfTheConfigs
if (mismatched)
Some(
"Binary version (" + depBinaryVersion + ") for dependency " + id +
@ -180,8 +183,7 @@ object IvyScalaUtil {
): Unit = {
val configurationNames = {
val names = module.getConfigurationsNames
if (configurations.isEmpty)
names
if (configurations.isEmpty) names
else {
val configSet = configurationSet(configurations)
configSet.intersect(HashSet(names: _*))

View File

@ -102,5 +102,6 @@ private[sbt] object ResolutionCache {
private val Name = "sbt-resolution-cache"
// use sbt-specific extra attributes so that resolved xml files do not get overwritten when using different Scala/sbt versions
private val ResolvedPattern = "[organisation]/[module]/" + Resolver.PluginPattern + "([branch]/)[revision]/[artifact].[ext]"
private val ResolvedPattern =
"[organisation]/[module]/" + Resolver.PluginPattern + "([branch]/)[revision]/[artifact].[ext]"
}

View File

@ -127,8 +127,12 @@ private[sbt] class CachedResolutionResolveCache {
val mesStr = (mes map excludeRuleString).mkString(",")
val os = extractOverrides(parent)
val moduleLevel = s"""dependencyOverrides=${os.mkString(",")};moduleExclusions=$mesStr"""
val depsString = s"""$mrid;${confMap.mkString(",")};isForce=${dd.isForce};isChanging=${dd.isChanging};isTransitive=${dd.isTransitive};""" +
s"""exclusions=${exclusions.mkString(",")};inclusions=${inclusions.mkString(",")};explicitArtifacts=${explicitArtifacts
val depsString = s"""$mrid;${confMap.mkString(
","
)};isForce=${dd.isForce};isChanging=${dd.isChanging};isTransitive=${dd.isTransitive};""" +
s"""exclusions=${exclusions.mkString(",")};inclusions=${inclusions.mkString(
","
)};explicitArtifacts=${explicitArtifacts
.mkString(",")};$moduleLevel;"""
val sha1 = Hash.toHex(
Hash(s"""graphVersion=${CachedResolutionResolveCache.graphVersion};$depsString""")
@ -158,15 +162,14 @@ private[sbt] class CachedResolutionResolveCache {
md0.getAllDependencyDescriptorMediators.getAllRules.asScala.toSeq.toVector sortBy {
case (k, _) =>
k.toString
} collect {
case (k: MapMatcher, v: OverrideDependencyDescriptorMediator) =>
val attr: Map[Any, Any] = k.getAttributes.asScala.toMap
val module = IvyModuleId.newInstance(
attr(IvyPatternHelper.ORGANISATION_KEY).toString,
attr(IvyPatternHelper.MODULE_KEY).toString
)
val pm = k.getPatternMatcher
IvyOverride(module, pm, v)
} collect { case (k: MapMatcher, v: OverrideDependencyDescriptorMediator) =>
val attr: Map[Any, Any] = k.getAttributes.asScala.toMap
val module = IvyModuleId.newInstance(
attr(IvyPatternHelper.ORGANISATION_KEY).toString,
attr(IvyPatternHelper.MODULE_KEY).toString
)
val pm = k.getPatternMatcher
IvyOverride(module, pm, v)
}
}
def getOrElseUpdateMiniGraph(
@ -200,8 +203,10 @@ private[sbt] class CachedResolutionResolveCache {
}
val staticGraphDirectory = miniGraphPath / "static"
val dynamicGraphDirectory = miniGraphPath / "dynamic"
val staticGraphPath = staticGraphDirectory / pathScalaVersion / pathSbtVersion / pathOrg / pathName / pathRevision / "graphs" / "graph.json"
val dynamicGraphPath = dynamicGraphDirectory / todayStr / logicalClock.toString / pathScalaVersion / pathSbtVersion / pathOrg / pathName / pathRevision / "graphs" / "graph.json"
val staticGraphPath =
staticGraphDirectory / pathScalaVersion / pathSbtVersion / pathOrg / pathName / pathRevision / "graphs" / "graph.json"
val dynamicGraphPath =
dynamicGraphDirectory / todayStr / logicalClock.toString / pathScalaVersion / pathSbtVersion / pathOrg / pathName / pathRevision / "graphs" / "graph.json"
def cleanDynamicGraph(): Unit = {
val list = IO.listFiles(dynamicGraphDirectory, DirectoryFilter).toList
list filterNot { d =>
@ -282,9 +287,12 @@ private[sbt] class CachedResolutionResolveCache {
val moduleIdMap = Map(conflicts map { x =>
x.module -> x
}: _*)
(surviving map moduleIdMap, evicted map moduleIdMap map {
_.withEvicted(true).withEvictedReason(Some(mgr.toString))
})
(
surviving map moduleIdMap,
evicted map moduleIdMap map {
_.withEvicted(true).withEvictedReason(Some(mgr.toString))
}
)
}
(conflictCache get ((cf0, cf1))) match {
case Some((surviving, evicted, mgr)) => reconstructReports(surviving, evicted, mgr)
@ -304,8 +312,7 @@ private[sbt] class CachedResolutionResolveCache {
def getOrElseUpdateProjectReport(mrid: ModuleRevisionId, logicalClock: LogicalClock)(
f: => Either[ResolveException, UpdateReport]
): Either[ResolveException, UpdateReport] =
if (projectReportCache contains (mrid -> logicalClock))
projectReportCache((mrid, logicalClock))
if (projectReportCache contains (mrid -> logicalClock)) projectReportCache((mrid, logicalClock))
else {
val oldKeys = projectReportCache.keys filter { case (_, clk) => clk != logicalClock }
projectReportCache --= oldKeys
@ -410,59 +417,58 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
Left(new ResolveException(messages, failed, failedPaths))
}
}
val (internal, external) = mds.partition {
case (_, _, dd) => cache.internalDependency(dd, projectResolver).isDefined
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 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
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 =>
try d.addDependencyConfiguration(conf(0), conf(1))
catch {
case _: Throwable => ()
} // An exception will be thrown if `conf(0)` doesn't exist.
}
case _ => Nil
}
}
dd match {
case d: DefaultDependencyDescriptor =>
configurationsInInternal foreach { c =>
val configurations = c.split(";").map(_.split("->"))
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 _ => ()
}
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 =
@ -485,21 +491,20 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
log: Logger
): Either[ResolveException, UpdateReport] =
if (!missingOk && (results exists { _.isLeft }))
Left(mergeErrors(md0, results collect { case Left(re) => re }))
Left(mergeErrors(md0, results collect { case Left(re) => re }))
else Right(mergeReports(md0, results collect { case Right(ur) => ur }, resolveTime, os, log))
def mergeErrors(md0: ModuleDescriptor, errors: Vector[ResolveException]): ResolveException = {
val messages = errors flatMap { _.messages }
val failed = errors flatMap { _.failed }
val failedPaths = errors flatMap {
_.failedPaths.toList map {
case (failed, paths) =>
if (paths.isEmpty) (failed, paths)
else
(
failed,
List(IvyRetrieve.toModuleID(md0.getResolvedModuleRevisionId)) ::: paths.toList.tail
)
_.failedPaths.toList map { case (failed, paths) =>
if (paths.isEmpty) (failed, paths)
else
(
failed,
List(IvyRetrieve.toModuleID(md0.getResolvedModuleRevisionId)) ::: paths.toList.tail
)
}
}
new ResolveException(messages, failed, ListMap(failedPaths: _*))
@ -579,12 +584,11 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
// this might take up some memory, but it's limited to a single
val reports1 = reports0 flatMap { filterReports }
val allModules0: Map[(String, String), Vector[OrganizationArtifactReport]] =
Map(orgNamePairs map {
case (organization, name) =>
val xs = reports1 filter { oar =>
oar.organization == organization && oar.name == name
}
((organization, name), xs)
Map(orgNamePairs map { case (organization, name) =>
val xs = reports1 filter { oar =>
oar.organization == organization && oar.name == name
}
((organization, name), xs)
}: _*)
// this returns a List of Lists of (org, name). should be deterministic
def detectLoops(
@ -766,8 +770,8 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
val completelyEvicted = xs forall { _.evicted }
val allCallers = xs flatMap { _.callers }
// Caller info is often repeated across the subprojects. We only need ModuleID info for later, so xs.head is ok.
val distinctByModuleId = allCallers.groupBy({ _.caller }).toVector map {
case (_, xs) => xs.head
val distinctByModuleId = allCallers.groupBy({ _.caller }).toVector map { case (_, xs) =>
xs.head
}
val allArtifacts = (xs flatMap { _.artifacts }).distinct
xs.head
@ -777,10 +781,9 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
}
val merged = (modules groupBy { m =>
(m.module.organization, m.module.name, m.module.revision)
}).toSeq.toVector flatMap {
case (_, xs) =>
if (xs.size < 2) xs
else Vector(mergeModuleReports(xs))
}).toSeq.toVector flatMap { case (_, xs) =>
if (xs.size < 2) xs
else Vector(mergeModuleReports(xs))
}
val conflicts = merged filter { m =>
!m.evicted && m.problem.isEmpty
@ -789,9 +792,12 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
else
resolveConflict(rootModuleConf, conflicts, os, log) match {
case (survivor, evicted) =>
(survivor ++ (merged filter { m =>
m.evicted || m.problem.isDefined
}), evicted)
(
survivor ++ (merged filter { m =>
m.evicted || m.problem.isDefined
}),
evicted
)
}
}
@ -869,9 +875,13 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
}) match {
case Some(m) =>
log.debug(s"- directly forced dependency: $m ${m.callers}")
(Vector(m), conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some("direct-force"))
}, "direct-force")
(
Vector(m),
conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some("direct-force"))
},
"direct-force"
)
case None =>
(conflicts find { m =>
m.callers.exists { _.isForceDependency }
@ -879,18 +889,26 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
// Ivy translates pom.xml dependencies to forced="true", so transitive force is broken.
case Some(m) if !ignoreTransitiveForce =>
log.debug(s"- transitively forced dependency: $m ${m.callers}")
(Vector(m), conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some("transitive-force"))
}, "transitive-force")
(
Vector(m),
conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some("transitive-force"))
},
"transitive-force"
)
case _ =>
val strategy = lcm.getStrategy
val infos = conflicts map { ModuleReportArtifactInfo(_) }
log.debug(s"- Using $strategy with $infos")
Option(strategy.findLatest(infos.toArray, None.orNull)) match {
case Some(ModuleReportArtifactInfo(m)) =>
(Vector(m), conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some(lcm.toString))
}, lcm.toString)
(
Vector(m),
conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some(lcm.toString))
},
lcm.toString
)
case _ => (conflicts, Vector(), lcm.toString)
}
}
@ -905,9 +923,13 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
mr.module.revision == ovrVersion
} match {
case Some(m) =>
(Vector(m), conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some("override"))
}, "override")
(
Vector(m),
conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some("override"))
},
"override"
)
case None =>
sys.error(
s"override dependency specifies $ovrVersion but no candidates were found: " + (conflicts map {
@ -925,7 +947,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
}).mkString("(", ", ", ")"))
)
case lcm: LatestConflictManager => useLatest(lcm)
case conflictManager => sys.error(s"Unsupported conflict manager $conflictManager")
case conflictManager => sys.error(s"Unsupported conflict manager $conflictManager")
}
}
if (conflicts.size == 2 && os.isEmpty) {

View File

@ -65,8 +65,10 @@ object ErrorMessageAuthenticator {
}
try Option(ivyOriginalField.get(ivy).asInstanceOf[Authenticator]) match {
case Some(_: ErrorMessageAuthenticator) => // We're already installed, no need to do the work again.
case originalOpt => installIntoIvyImpl(originalOpt)
case Some(
_: ErrorMessageAuthenticator
) => // We're already installed, no need to do the work again.
case originalOpt => installIntoIvyImpl(originalOpt)
} catch {
case t: Throwable =>
Message.debug(

View File

@ -47,52 +47,53 @@ class GigahorseUrlHandler(http: OkHttpClient) extends AbstractURLHandler {
val response = http.newCall(request.build()).execute()
try {
val infoOption = try {
val infoOption =
try {
if (checkStatusCode(url, response)) {
val bodyCharset =
BasicURLHandler.getCharSetFromContentType(
Option(response.body().contentType()).map(_.toString).orNull
if (checkStatusCode(url, response)) {
val bodyCharset =
BasicURLHandler.getCharSetFromContentType(
Option(response.body().contentType()).map(_.toString).orNull
)
Some(
new SbtUrlInfo(
true,
response.body().contentLength(),
lastModifiedTimestamp(response),
bodyCharset
)
)
Some(
new SbtUrlInfo(
true,
response.body().contentLength(),
lastModifiedTimestamp(response),
bodyCharset
)
)
} else None
//
// Commented out for now - can potentially be used for non HTTP urls
//
// val contentLength: Long = con.getContentLengthLong
// if (contentLength <= 0) None
// else {
// // TODO: not HTTP... maybe we *don't* want to default to ISO-8559-1 here?
// val bodyCharset = BasicURLHandler.getCharSetFromContentType(con.getContentType)
// Some(new SbtUrlInfo(true, contentLength, con.getLastModified(), bodyCharset))
// }
} else None
//
// Commented out for now - can potentially be used for non HTTP urls
//
// val contentLength: Long = con.getContentLengthLong
// if (contentLength <= 0) None
// else {
// // TODO: not HTTP... maybe we *don't* want to default to ISO-8559-1 here?
// val bodyCharset = BasicURLHandler.getCharSetFromContentType(con.getContentType)
// Some(new SbtUrlInfo(true, contentLength, con.getLastModified(), bodyCharset))
// }
} catch {
case e: UnknownHostException =>
Message.warn("Host " + e.getMessage + " not found. url=" + url)
Message.info(
"You probably access the destination server through "
+ "a proxy server that is not well configured."
)
None
case e: IOException =>
Message.error("Server access Error: " + e.getMessage + " url=" + url)
None
}
} catch {
case e: UnknownHostException =>
Message.warn("Host " + e.getMessage + " not found. url=" + url)
Message.info(
"You probably access the destination server through "
+ "a proxy server that is not well configured."
)
None
case e: IOException =>
Message.error("Server access Error: " + e.getMessage + " url=" + url)
None
}
infoOption.getOrElse(UNAVAILABLE)
} finally {
response.close()
}
}
//The caller of this *MUST* call Response.close()
// The caller of this *MUST* call Response.close()
private def getUrl(url0: URL): okhttp3.Response = {
// Install the ErrorMessageAuthenticator
if ("http" == url0.getProtocol || "https" == url0.getProtocol) {
@ -117,7 +118,7 @@ class GigahorseUrlHandler(http: OkHttpClient) extends AbstractURLHandler {
response
} catch {
case NonFatal(e) =>
//ensure the response gets closed if there's an error
// ensure the response gets closed if there's an error
response.close()
throw e
}
@ -125,7 +126,7 @@ class GigahorseUrlHandler(http: OkHttpClient) extends AbstractURLHandler {
}
def openStream(url: URL): InputStream = {
//It's assumed that the caller of this will call close() on the supplied inputstream,
// It's assumed that the caller of this will call close() on the supplied inputstream,
// thus closing the OkHTTP request
getUrl(url).body().byteStream()
}
@ -201,7 +202,8 @@ class GigahorseUrlHandler(http: OkHttpClient) extends AbstractURLHandler {
}
}
private val ErrorBodyTruncateLen = 512 // in case some bad service returns files rather than messages in error bodies
private val ErrorBodyTruncateLen =
512 // in case some bad service returns files rather than messages in error bodies
private val DefaultErrorCharset = java.nio.charset.StandardCharsets.UTF_8
// neurotic resource managemement...

View File

@ -56,8 +56,8 @@ private[sbt] object IvyCredentialsLookup {
* A mapping of host -> realms in the ivy credentials store.
*/
def realmsForHost: Map[String, Set[String]] =
(keyringKeys collect {
case x: Realm => x
(keyringKeys collect { case x: Realm =>
x
} groupBy { realm =>
realm.host
} mapValues { realms =>

View File

@ -13,14 +13,14 @@ private[sbt] object MergeDescriptors {
a.isTransitive == b.isTransitive &&
a.getParentRevisionId == b.getParentRevisionId &&
a.getNamespace == b.getNamespace && {
val amrid = a.getDependencyRevisionId
val bmrid = b.getDependencyRevisionId
amrid == bmrid
} && {
val adyn = a.getDynamicConstraintDependencyRevisionId
val bdyn = b.getDynamicConstraintDependencyRevisionId
adyn == bdyn
}
val amrid = a.getDependencyRevisionId
val bmrid = b.getDependencyRevisionId
amrid == bmrid
} && {
val adyn = a.getDynamicConstraintDependencyRevisionId
val bdyn = b.getDynamicConstraintDependencyRevisionId
adyn == bdyn
}
def apply(a: DependencyDescriptor, b: DependencyDescriptor): DependencyDescriptor = {
assert(mergeable(a, b))

View File

@ -48,17 +48,18 @@ private[sbt] class ParallelResolveEngine(
}
// Farm out the dependencies for parallel download
implicit val ec = ParallelResolveEngine.resolveExecutionContext
val allDownloadsFuture = Future.traverse(report.getDependencies.asScala) {
case dep: IvyNode =>
Future {
if (!(dep.isCompletelyEvicted || dep.hasProblem) &&
dep.getModuleRevision != null) {
Some(downloadNodeArtifacts(dep, artifactFilter, options))
} else None
}
val allDownloadsFuture = Future.traverse(report.getDependencies.asScala) { case dep: IvyNode =>
Future {
if (
!(dep.isCompletelyEvicted || dep.hasProblem) &&
dep.getModuleRevision != null
) {
Some(downloadNodeArtifacts(dep, artifactFilter, options))
} else None
}
}
val allDownloads = Await.result(allDownloadsFuture, Duration.Inf)
//compute total downloaded size
// compute total downloaded size
val totalSize = allDownloads.foldLeft(0L) {
case (size, Some(download)) =>
val dependency = download.dep
@ -67,8 +68,10 @@ private[sbt] class ParallelResolveEngine(
val configurationReport = report.getConfigurationReport(configuration)
// Take into account artifacts required by the given configuration
if (dependency.isEvicted(configuration) ||
dependency.isBlacklisted(configuration)) {
if (
dependency.isEvicted(configuration) ||
dependency.isBlacklisted(configuration)
) {
configurationReport.addDependency(dependency)
} else configurationReport.addDependency(dependency, download.report)
}

View File

@ -124,7 +124,8 @@ private[sbt] case class SbtChainResolver(
/** If None, module was not found. Otherwise, hit. */
type TriedResolution = Option[(ResolvedModuleRevision, DependencyResolver)]
/** Attempts to resolve the artifact from each of the resolvers in the chain.
/**
* Attempts to resolve the artifact from each of the resolvers in the chain.
*
* Contract:
* 1. It doesn't resolve anything when there is a resolved module, `isReturnFirst` is
@ -155,8 +156,8 @@ private[sbt] case class SbtChainResolver(
currentlyResolved = Option(resolver.getDependency(descriptor, data))
if (currentlyResolved eq previouslyResolved) None
else if (useLatest) {
currentlyResolved.map(
x => (reparseModuleDescriptor(descriptor, data, resolver, x), resolver)
currentlyResolved.map(x =>
(reparseModuleDescriptor(descriptor, data, resolver, x), resolver)
)
} else currentlyResolved.map(x => (forcedRevision(x), resolver))
}
@ -174,7 +175,8 @@ private[sbt] case class SbtChainResolver(
val oldLatest: Option[LatestStrategy] =
setLatestIfRequired(resolver, Option(getLatestStrategy))
try Right(performResolution(resolver))
catch { case NonFatal(t) => reportError(t, resolver); Left(t) } finally {
catch { case NonFatal(t) => reportError(t, resolver); Left(t) }
finally {
oldLatest.foreach(_ => doSetLatestStrategy(resolver, oldLatest))
checkInterrupted()
}
@ -189,34 +191,33 @@ private[sbt] case class SbtChainResolver(
data: ResolveData
): Option[ResolvedModuleRevision] = {
val sortedRevisions = foundRevisions.sortBy {
case (rmr, resolver) =>
val publicationDate = rmr.getPublicationDate
val descriptorDate = rmr.getDescriptor.getPublicationDate
Message.warn(s"Sorting results from $rmr, using $publicationDate and $descriptorDate.")
// Just issue warning about issues with publication date, and fake one on it for now
val chosenPublicationDate = Option(publicationDate).orElse(Option(descriptorDate))
chosenPublicationDate match {
case Some(date) => date.getTime
case None =>
val id = rmr.getId
val resolvedResource = (resolver.findIvyFileRef(descriptor, data), rmr.getDescriptor)
resolvedResource match {
case (res: ResolvedResource, dmd: DefaultModuleDescriptor) =>
val resolvedPublicationDate = new java.util.Date(res.getLastModified)
Message.debug(s"No publication date from resolver $resolver for $id.")
Message.debug(s"Setting publication date to: $resolvedPublicationDate.")
dmd.setPublicationDate(resolvedPublicationDate)
res.getLastModified
case (ivf, dmd) =>
// The dependency is specified by a direct URL or some sort of non-ivy file
if (ivf == null && descriptor.isChanging)
Message.warn(s"$prefix: changing dependency $id with no ivy/pom file!")
if (dmd == null)
Message.warn(s"$prefix: no publication date from resolver $resolver for $id")
0L
}
}
val sortedRevisions = foundRevisions.sortBy { case (rmr, resolver) =>
val publicationDate = rmr.getPublicationDate
val descriptorDate = rmr.getDescriptor.getPublicationDate
Message.warn(s"Sorting results from $rmr, using $publicationDate and $descriptorDate.")
// Just issue warning about issues with publication date, and fake one on it for now
val chosenPublicationDate = Option(publicationDate).orElse(Option(descriptorDate))
chosenPublicationDate match {
case Some(date) => date.getTime
case None =>
val id = rmr.getId
val resolvedResource = (resolver.findIvyFileRef(descriptor, data), rmr.getDescriptor)
resolvedResource match {
case (res: ResolvedResource, dmd: DefaultModuleDescriptor) =>
val resolvedPublicationDate = new java.util.Date(res.getLastModified)
Message.debug(s"No publication date from resolver $resolver for $id.")
Message.debug(s"Setting publication date to: $resolvedPublicationDate.")
dmd.setPublicationDate(resolvedPublicationDate)
res.getLastModified
case (ivf, dmd) =>
// The dependency is specified by a direct URL or some sort of non-ivy file
if (ivf == null && descriptor.isChanging)
Message.warn(s"$prefix: changing dependency $id with no ivy/pom file!")
if (dmd == null)
Message.warn(s"$prefix: no publication date from resolver $resolver for $id")
0L
}
}
}
val firstHit = sortedRevisions.reverse.headOption
@ -277,12 +278,11 @@ private[sbt] case class SbtChainResolver(
}
/** Cleans unnecessary module id information not provided by [[IvyRetrieve.toModuleID()]]. */
private final val moduleResolvers = updateOptions.moduleResolvers.map {
case (key, value) =>
val cleanKey = ModuleID(key.organization, key.name, key.revision)
.withExtraAttributes(key.extraAttributes)
.withBranchName(key.branchName)
cleanKey -> value
private final val moduleResolvers = updateOptions.moduleResolvers.map { case (key, value) =>
val cleanKey = ModuleID(key.organization, key.name, key.revision)
.withExtraAttributes(key.extraAttributes)
.withBranchName(key.branchName)
cleanKey -> value
}
/**
@ -309,7 +309,8 @@ private[sbt] case class SbtChainResolver(
def findInterProjectResolver(resolvers: Seq[DependencyResolver]): Option[DependencyResolver] =
resolvers.find(_.getName == ProjectResolver.InterProject)
/** Gets the dependency for a given descriptor with the pertinent resolve data.
/**
* Gets the dependency for a given descriptor with the pertinent resolve data.
*
* This is a custom sbt chain operation that produces better error output and deals with
* cases that the conventional ivy resolver does not. It accumulates the resolution of