update scalafmt

This commit is contained in:
xuwei-k 2023-06-25 10:10:11 +09:00
parent 8d46a02c50
commit 9a1d836b4e
52 changed files with 736 additions and 619 deletions

View File

@ -1,11 +1,12 @@
version = 2.0.0 version = 3.7.4
maxColumn = 100 maxColumn = 100
project.git = true project.git = true
project.excludeFilters = [ /sbt-test/, /input_sources/, /contraband-scala/ ] project.excludeFilters = [ /sbt-test/, /input_sources/, /contraband-scala/ ]
# http://docs.scala-lang.org/style/scaladoc.html recommends the JavaDoc style. # http://docs.scala-lang.org/style/scaladoc.html recommends the JavaDoc style.
# scala/scala is written that way too https://github.com/scala/scala/blob/v2.12.2/src/library/scala/Predef.scala # scala/scala is written that way too https://github.com/scala/scala/blob/v2.12.2/src/library/scala/Predef.scala
docstrings = JavaDoc docstrings.style = Asterisk
docstrings.wrap = no
# This also seems more idiomatic to include whitespace in import x.{ yyy } # This also seems more idiomatic to include whitespace in import x.{ yyy }
spaces.inImportCurlyBraces = true spaces.inImportCurlyBraces = true
@ -16,6 +17,8 @@ align.openParenCallSite = false
align.openParenDefnSite = false align.openParenDefnSite = false
# For better code clarity # For better code clarity
danglingParentheses = true danglingParentheses.preset = true
trailingCommas = preserve trailingCommas = preserve
runner.dialect = Scala212Source3

View File

@ -3,7 +3,7 @@ import Path._
import com.typesafe.tools.mima.core._, ProblemFilters._ import com.typesafe.tools.mima.core._, ProblemFilters._
val _ = { val _ = {
//https://github.com/sbt/contraband/issues/122 // https://github.com/sbt/contraband/issues/122
sys.props += ("line.separator" -> "\n") sys.props += ("line.separator" -> "\n")
} }
Global / semanticdbEnabled := !(Global / insideCI).value Global / semanticdbEnabled := !(Global / insideCI).value
@ -90,11 +90,10 @@ val mimaSettings = Def settings (
"1.4.0", "1.4.0",
"1.5.0", "1.5.0",
"1.6.0", "1.6.0",
) map ( ) map (version =>
version => organization.value %% moduleName.value % version
organization.value %% moduleName.value % version cross (if (crossPaths.value) CrossVersion.binary else CrossVersion.disabled)
cross (if (crossPaths.value) CrossVersion.binary else CrossVersion.disabled) ),
),
) )
lazy val lmRoot = (project in file(".")) lazy val lmRoot = (project in file("."))

View File

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

View File

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

View File

@ -71,7 +71,7 @@ object VersionRange {
case _: NumberFormatException => case _: NumberFormatException =>
// TODO - if the version doesn't meet our expectations, maybe we just issue a hard // TODO - if the version doesn't meet our expectations, maybe we just issue a hard
// error instead of softly ignoring the attempt to rewrite. // 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 revision
} }
} }

View File

@ -36,7 +36,8 @@ private[sbt] object VersionSchemes {
case x => sys.error(s"unknown version scheme: $x") 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) 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[sbt] val BinCompatV = raw"""$basicVersion(-$tagPattern)?-bin(-.*)?""".r
private val CandidateV = raw"""$basicVersion(-RC\d+)""".r private val CandidateV = raw"""$basicVersion(-RC\d+)""".r
private val MilestonV = raw"""$basicVersion(-M$tagPattern)""".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 val NonReleaseV_1 = raw"""$basicVersion(-$tagPattern)""".r // 1 word suffix, after a dash
private[sbt] val PartialVersion = raw"""($longPattern)\.($longPattern)(?:\..+)?""".r private[sbt] val PartialVersion = raw"""($longPattern)\.($longPattern)(?:\..+)?""".r

View File

@ -21,11 +21,11 @@ final class Configuration private[sbt] (
override def equals(o: Any): Boolean = o match { override def equals(o: Any): Boolean = o match {
case x: Configuration => case x: Configuration =>
(this.id == x.id) && (this.id == x.id) &&
(this.name == x.name) && (this.name == x.name) &&
(this.description == x.description) && (this.description == x.description) &&
(this.isPublic == x.isPublic) && (this.isPublic == x.isPublic) &&
(this.extendsConfigs == x.extendsConfigs) && (this.extendsConfigs == x.extendsConfigs) &&
(this.transitive == x.transitive) (this.transitive == x.transitive)
case _ => false case _ => false
} }

View File

@ -37,13 +37,13 @@ private[librarymanagement] abstract class CrossVersionFunctions {
*/ */
def fullWith(prefix: String, suffix: String): CrossVersion = Full(prefix, suffix) 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() def binary: CrossVersion = Binary()
/** Disables cross versioning for a module. */ /** Disables cross versioning for a module. */
def disabled: CrossVersion = sbt.librarymanagement.Disabled 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) 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) 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 val PartialVersion = CrossVersionUtil.PartialVersion
/** Extracts the major and minor components of a version string `s` or returns `None` if the version is improperly formatted. */ /** 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 = ): ArtifactFilter =
new ArtifactFilter { new ArtifactFilter {
def apply(a: Artifact): Boolean = 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 "") .accept(a.classifier getOrElse "")
} }

View File

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

View File

@ -157,30 +157,29 @@ final class EvictionError private[sbt] (
val out: mutable.ListBuffer[String] = mutable.ListBuffer() val out: mutable.ListBuffer[String] = mutable.ListBuffer()
out += "found version conflict(s) in library dependencies; some are suspected to be binary incompatible:" out += "found version conflict(s) in library dependencies; some are suspected to be binary incompatible:"
out += "" out += ""
evictions.foreach({ evictions.foreach({ case (a, scheme) =>
case (a, scheme) => val revs = a.evicteds map { _.module.revision }
val revs = a.evicteds map { _.module.revision } val revsStr =
val revsStr = if (revs.size <= 1) revs.mkString else "{" + revs.distinct.mkString(", ") + "}"
if (revs.size <= 1) revs.mkString else "{" + revs.distinct.mkString(", ") + "}" val seen: mutable.Set[ModuleID] = mutable.Set()
val seen: mutable.Set[ModuleID] = mutable.Set() val callers: List[String] = (a.evicteds.toList ::: a.winner.toList) flatMap { r =>
val callers: List[String] = (a.evicteds.toList ::: a.winner.toList) flatMap { r => val rev = r.module.revision
val rev = r.module.revision r.callers.toList flatMap { caller =>
r.callers.toList flatMap { caller => if (seen(caller.caller)) Nil
if (seen(caller.caller)) Nil else {
else { seen += caller.caller
seen += caller.caller List(f"\t +- ${caller}%-50s (depends on $rev)")
List(f"\t +- ${caller}%-50s (depends on $rev)")
}
} }
} }
val que = if (assumed) "?" else "" }
val winnerRev = a.winner match { val que = if (assumed) "?" else ""
case Some(r) => s":${r.module.revision} ($scheme$que) is selected over ${revsStr}" val winnerRev = a.winner match {
case _ => " is evicted for all versions" 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("") val title = s"\t* ${a.organization}:${a.name}$winnerRev"
out ++= lines val lines = title :: (if (a.showCallers) callers.reverse else Nil) ::: List("")
out ++= lines
}) })
out.toList out.toList
} }

View File

@ -196,7 +196,7 @@ final class EvictionPair private[sbt] (
override def equals(o: Any): Boolean = o match { override def equals(o: Any): Boolean = o match {
case o: EvictionPair => case o: EvictionPair =>
(this.organization == o.organization) && (this.organization == o.organization) &&
(this.name == o.name) (this.name == o.name)
case _ => false case _ => false
} }
override def hashCode: Int = { override def hashCode: Int = {
@ -279,10 +279,12 @@ object EvictionWarning {
} }
confs flatMap { confReport => confs flatMap { confReport =>
confReport.details map { detail => confReport.details map { detail =>
if ((detail.modules exists { _.evicted }) && if (
!(buffer exists { x => (detail.modules exists { _.evicted }) &&
(x.organization == detail.organization) && (x.name == detail.name) !(buffer exists { x =>
})) { (x.organization == detail.organization) && (x.name == detail.name)
})
) {
buffer += detail buffer += detail
} }
} }
@ -298,7 +300,7 @@ object EvictionWarning {
module.scalaModuleInfo match { module.scalaModuleInfo match {
case Some(s) => case Some(s) =>
organization == s.scalaOrganization && organization == s.scalaOrganization &&
(name == LibraryID) || (name == CompilerID) (name == LibraryID) || (name == CompilerID)
case _ => false case _ => false
} }

View File

@ -37,10 +37,10 @@ private[librarymanagement] abstract class ModuleIDExtra {
protected def toStringImpl: String = protected def toStringImpl: String =
s"""$organization:$name:$revision""" + s"""$organization:$name:$revision""" +
(configurations match { case Some(s) => ":" + s; case None => "" }) + { (configurations match { case Some(s) => ":" + s; case None => "" }) + {
val attr = attributeString val attr = attributeString
if (attr == "") "" if (attr == "") ""
else " " + attr else " " + attr
} + } +
(if (extraAttributes.isEmpty) "" else " " + extraString) (if (extraAttributes.isEmpty) "" else " " + extraString)
protected def attributeString: String = { protected def attributeString: String = {
@ -95,10 +95,10 @@ private[librarymanagement] abstract class ModuleIDExtra {
}) })
// () required for chaining // () 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() 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) def intransitive(): ModuleID = withIsTransitive(false)
/** /**

View File

@ -185,7 +185,7 @@ private[librarymanagement] abstract class ResolverFunctions {
"https://repository.apache.org/content/repositories/snapshots/" "https://repository.apache.org/content/repositories/snapshots/"
) )
/** 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] = def combineDefaultResolvers(userResolvers: Vector[Resolver]): Vector[Resolver] =
combineDefaultResolvers(userResolvers, mavenCentral = true) combineDefaultResolvers(userResolvers, mavenCentral = true)
@ -232,7 +232,10 @@ private[librarymanagement] abstract class ResolverFunctions {
single(JCenterRepository, jcenter) ++ single(JCenterRepository, jcenter) ++
(xs.partition(_ == DefaultMavenRepository) match { (xs.partition(_ == DefaultMavenRepository) match {
case (_, xs) => 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?
}) })
}) })
} }
@ -240,7 +243,7 @@ private[librarymanagement] abstract class ResolverFunctions {
private def single[T](value: T, nonEmpty: Boolean): Vector[T] = private def single[T](value: T, nonEmpty: Boolean): Vector[T] =
if (nonEmpty) Vector(value) else Vector.empty 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] { sealed abstract class Define[RepositoryType <: SshBasedRepository] {
/** Subclasses should implement this method to */ /** Subclasses should implement this method to */
@ -269,8 +272,8 @@ private[librarymanagement] abstract class ResolverFunctions {
* patterns will be resolved. `basePatterns` are the initial patterns to use. * 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. * 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)( def apply(name: String, hostname: String, basePath: String)(implicit
implicit basePatterns: Patterns basePatterns: Patterns
): RepositoryType = ): RepositoryType =
apply(name, Some(hostname), None, Some(basePath)) apply(name, Some(hostname), None, Some(basePath))
@ -278,8 +281,8 @@ private[librarymanagement] abstract class ResolverFunctions {
* Constructs this repository type with the given `name`, `hostname`, and `port`. `basePatterns` are the initial patterns to use. * 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. * 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)( def apply(name: String, hostname: String, port: Int)(implicit
implicit basePatterns: Patterns basePatterns: Patterns
): RepositoryType = ): RepositoryType =
apply(name, Some(hostname), Some(port), None) apply(name, Some(hostname), Some(port), None)
@ -288,8 +291,8 @@ private[librarymanagement] abstract class ResolverFunctions {
* patterns will be resolved. `basePatterns` are the initial patterns to use. * 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. * 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)( def apply(name: String, hostname: String, port: Int, basePath: String)(implicit
implicit basePatterns: Patterns basePatterns: Patterns
): RepositoryType = ): RepositoryType =
apply(name, Some(hostname), Some(port), Some(basePath)) apply(name, Some(hostname), Some(port), Some(basePath))
@ -304,13 +307,13 @@ private[librarymanagement] abstract class ResolverFunctions {
construct(name, SshConnection(None, hostname, port), resolvePatterns(basePath, basePatterns)) 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] { object ssh extends Define[SshRepository] {
protected def construct(name: String, connection: SshConnection, patterns: Patterns) = protected def construct(name: String, connection: SshConnection, patterns: Patterns) =
SshRepository(name, connection, patterns, None) 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] { object sftp extends Define[SftpRepository] {
protected def construct(name: String, connection: SshConnection, patterns: Patterns) = protected def construct(name: String, connection: SshConnection, patterns: Patterns) =
SftpRepository(name, connection, patterns) SftpRepository(name, connection, patterns)
@ -348,8 +351,8 @@ private[librarymanagement] abstract class ResolverFunctions {
def apply(name: String, baseURL: URL)(implicit basePatterns: Patterns): URLRepository = def apply(name: String, baseURL: URL)(implicit basePatterns: Patterns): URLRepository =
baseRepository(baseURL.toURI.normalize.toString)(URLRepository(name, _)) baseRepository(baseURL.toURI.normalize.toString)(URLRepository(name, _))
} }
private def baseRepository[T](base: String)(construct: Patterns => T)( private def baseRepository[T](base: String)(construct: Patterns => T)(implicit
implicit basePatterns: Patterns basePatterns: Patterns
): T = ): T =
construct(resolvePatterns(base, basePatterns)) construct(resolvePatterns(base, basePatterns))
@ -381,7 +384,7 @@ private[librarymanagement] abstract class ResolverFunctions {
} }
def defaultFileConfiguration = FileConfiguration(true, None) def defaultFileConfiguration = FileConfiguration(true, None)
def mavenStylePatterns = Patterns().withArtifactPatterns(Vector(mavenStyleBasePattern)) def mavenStylePatterns = Patterns().withArtifactPatterns(Vector(mavenStyleBasePattern))
def ivyStylePatterns = defaultIvyPatterns //Patterns(Nil, Nil, false) def ivyStylePatterns = defaultIvyPatterns // Patterns(Nil, Nil, false)
def defaultPatterns = mavenStylePatterns def defaultPatterns = mavenStylePatterns
def mavenStyleBasePattern = def mavenStyleBasePattern =
@ -397,10 +400,13 @@ private[librarymanagement] abstract class ResolverFunctions {
val findQuoted = "\\$\\{([^\\}]*)\\}".r val findQuoted = "\\$\\{([^\\}]*)\\}".r
val env = "env\\.(.*)".r val env = "env\\.(.*)".r
findQuoted.replaceAllIn(str, _.group(1) match { findQuoted.replaceAllIn(
case env(variable) => sys.env.getOrElse(variable, "") str,
case property => sys.props.getOrElse(property, "") _.group(1) match {
}) case env(variable) => sys.env.getOrElse(variable, "")
case property => sys.props.getOrElse(property, "")
}
)
} }
private[this] def mavenLocalDir: File = { private[this] def mavenLocalDir: File = {
def loadHomeFromSettings(f: () => File): Option[File] = def loadHomeFromSettings(f: () => File): Option[File] =
@ -423,7 +429,9 @@ private[librarymanagement] abstract class ResolverFunctions {
} }
sys.props.get("maven.repo.local").map(new File(_)) orElse sys.props.get("maven.repo.local").map(new File(_)) orElse
loadHomeFromSettings(() => new File(sbt.io.Path.userHome, ".m2/settings.xml")) 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") new File(sbt.io.Path.userHome, ".m2/repository")
} }
// TODO - should this just be the *exact* same as mavenLocal? probably... // 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 = { private[sbt] def recomputeStamps(): UpdateReport = {
val files = report.cachedDescriptor +: allFiles val files = report.cachedDescriptor +: allFiles
val stamps = files val stamps = files
.map( .map(f =>
f => (
( f,
f, // TODO: The list of files may also contain some odd files that do not actually exist like:
// 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".
// "./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
// IO.getModifiedTimeOrZero() will just return zero, but the list of files should not contain such // files to begin with, in principle.
// files to begin with, in principle. IO.getModifiedTimeOrZero(f)
IO.getModifiedTimeOrZero(f) )
)
) )
.toMap .toMap
UpdateReport(report.cachedDescriptor, report.configurations, report.stats, stamps) UpdateReport(report.cachedDescriptor, report.configurations, report.stats, stamps)
@ -65,13 +64,13 @@ final class RichUpdateReport(report: UpdateReport) {
file 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 = def filter(f: DependencyFilter): UpdateReport =
moduleReportMap { (configuration, modReport) => moduleReportMap { (configuration, modReport) =>
modReport modReport
.withArtifacts( .withArtifacts(
modReport.artifacts filter { modReport.artifacts filter { case (art, _) =>
case (art, _) => f(configuration, modReport.module, art) f(configuration, modReport.module, art)
} }
) )
.withMissingArtifacts( .withMissingArtifacts(

View File

@ -10,9 +10,13 @@ final class ResolveException(
val failedPaths: Map[ModuleID, Seq[ModuleID]] val failedPaths: Map[ModuleID, Seq[ModuleID]]
) extends RuntimeException(messages.mkString("\n")) { ) extends RuntimeException(messages.mkString("\n")) {
def this(messages: Seq[String], failed: Seq[ModuleID]) = def this(messages: Seq[String], failed: Seq[ModuleID]) =
this(messages, failed, Map(failed map { m => this(
m -> Nil messages,
}: _*)) failed,
Map(failed map { m =>
m -> Nil
}: _*)
)
} }
/** /**
@ -30,13 +34,12 @@ object UnresolvedWarning {
config: UnresolvedWarningConfiguration config: UnresolvedWarningConfiguration
): UnresolvedWarning = { ): UnresolvedWarning = {
def modulePosition(m0: ModuleID): Option[SourcePosition] = def modulePosition(m0: ModuleID): Option[SourcePosition] =
config.modulePositions.find { config.modulePositions.find { case (m, _) =>
case (m, _) => (m.organization == m0.organization) &&
(m.organization == m0.organization) && (m0.name startsWith m.name) &&
(m0.name startsWith m.name) && (m.revision == m0.revision)
(m.revision == m0.revision) } map { case (_, p) =>
} map { p
case (_, p) => p
} }
val failedPaths = err.failed map { (x: ModuleID) => val failedPaths = err.failed map { (x: ModuleID) =>
err.failedPaths(x).toList.reverse map { id => err.failedPaths(x).toList.reverse map { id =>
@ -67,9 +70,8 @@ object UnresolvedWarning {
if (path.nonEmpty) { if (path.nonEmpty) {
val head = path.head val head = path.head
buffer += "\t\t" + head._1.toString + sourcePosStr(head._2) buffer += "\t\t" + head._1.toString + sourcePosStr(head._2)
path.tail foreach { path.tail foreach { case (m, pos) =>
case (m, pos) => buffer += "\t\t +- " + m.toString + sourcePosStr(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 = def retrieve(f: (ConfigRef, ModuleID, Artifact, File) => File): ConfigurationReport =
ConfigurationReport(configuration, modules map { ConfigurationReport(
_.retrieve((mid, art, file) => f(configuration, mid, art, file)) configuration,
}, details) modules map {
_.retrieve((mid, art, file) => f(configuration, mid, art, file))
},
details
)
} }
private[librarymanagement] abstract class ModuleReportExtra { private[librarymanagement] abstract class ModuleReportExtra {
@ -124,24 +128,23 @@ private[librarymanagement] abstract class UpdateReportExtra {
/** All resolved modules in all configurations. */ /** All resolved modules in all configurations. */
def allModules: Vector[ModuleID] = { def allModules: Vector[ModuleID] = {
val key = (m: ModuleID) => (m.organization, m.name, m.revision) val key = (m: ModuleID) => (m.organization, m.name, m.revision)
configurations.flatMap(_.allModules).groupBy(key).toVector map { configurations.flatMap(_.allModules).groupBy(key).toVector map { case (_, v) =>
case (_, v) => v reduceLeft { (agg, x) =>
v reduceLeft { (agg, x) => agg.withConfigurations(
agg.withConfigurations( (agg.configurations, x.configurations) match {
(agg.configurations, x.configurations) match { case (None, _) => x.configurations
case (None, _) => x.configurations case (Some(ac), None) => Some(ac)
case (Some(ac), None) => Some(ac) case (Some(ac), Some(xc)) => Some(s"$ac;$xc")
case (Some(ac), Some(xc)) => Some(s"$ac;$xc") }
} )
) }
}
} }
} }
def retrieve(f: (ConfigRef, ModuleID, Artifact, File) => File): UpdateReport = def retrieve(f: (ConfigRef, ModuleID, Artifact, File) => File): UpdateReport =
UpdateReport(cachedDescriptor, configurations map { _ retrieve f }, stats, stamps) 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) 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. */ /** 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. * 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. * Also API compatibility is expected even when the first segment is zero.
*/ */
@ -172,7 +173,8 @@ object VersionNumber {
PackVer.isCompatible(v1, v2) 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. * 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. * 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 { object EarlySemVer extends VersionNumberCompatibility {
import SemVer._ import SemVer._

View File

@ -56,6 +56,6 @@ object ConfigMacroSpec extends Properties("ConfigMacroSpec") {
s"Actual isPublic: ${c.isPublic}" |: s"Actual isPublic: ${c.isPublic}" |:
(c.id == id) && (c.id == id) &&
(c.name == name) && (c.name == name) &&
(c.isPublic == isPublic) (c.isPublic == isPublic)
} }
} }

View File

@ -148,13 +148,12 @@ class VersionNumberSpec extends AnyFreeSpec with Matchers with Inside {
ts: Seq[String], ts: Seq[String],
es: Seq[String] es: Seq[String]
): Unit = ): Unit =
s"should parse to ($ns, $ts, $es)" in inside(v.value) { s"should parse to ($ns, $ts, $es)" in inside(v.value) { case VersionNumber(ns1, ts1, es1) =>
case VersionNumber(ns1, ts1, es1) => (ns1 shouldBe ns)
(ns1 shouldBe ns) (ts1 shouldBe ts)
(ts1 shouldBe ts) (es1 shouldBe es)
(es1 shouldBe es) (VersionNumber(ns, ts, es).toString shouldBe v.value)
(VersionNumber(ns, ts, es).toString shouldBe v.value) (VersionNumber(ns, ts, es) shouldBe VersionNumber(ns, ts, es))
(VersionNumber(ns, ts, es) shouldBe VersionNumber(ns, ts, es))
} }
private[this] def assertParsesToError(v: VersionString): Unit = private[this] def assertParsesToError(v: VersionString): Unit =

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 * 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 * 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 { 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. */ /** 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) 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 lockGlobalCache[T](action: => T): T = lock(ivyCache.lockFile)(action)
private def lock[T](file: File)(action: => T): T = private def lock[T](file: File)(action: => T): T =
globalLock(file, new Callable[T] { def call = action }) globalLock(file, new Callable[T] { def call = action })

View File

@ -157,109 +157,108 @@ private[sbt] object ConvertResolver {
(updateOptions.resolverConverter orElse defaultConvert)((r, settings, log)) (updateOptions.resolverConverter orElse defaultConvert)((r, settings, log))
/** The default implementation of converter. */ /** The default implementation of converter. */
lazy val defaultConvert: ResolverConverter = { lazy val defaultConvert: ResolverConverter = { case (r, settings, log) =>
case (r, settings, log) => val managedChecksums = Option(settings.getVariable(ManagedChecksums)) match {
val managedChecksums = Option(settings.getVariable(ManagedChecksums)) match { case Some(x) => x.toBoolean
case Some(x) => x.toBoolean case _ => false
case _ => false }
} r match {
r match { case repo: MavenRepository => {
case repo: MavenRepository => { val pattern = Collections.singletonList(
val pattern = Collections.singletonList( Resolver.resolvePattern(repo.root, Resolver.mavenStyleBasePattern)
Resolver.resolvePattern(repo.root, Resolver.mavenStyleBasePattern) )
) final class PluginCapableResolver
final class PluginCapableResolver extends IBiblioResolver
extends IBiblioResolver with ChecksumFriendlyURLResolver
with ChecksumFriendlyURLResolver with DescriptorRequired {
with DescriptorRequired { override val managedChecksumsEnabled: Boolean = managedChecksums
override val managedChecksumsEnabled: Boolean = managedChecksums override def getResource(resource: Resource, dest: File): Long = get(resource, dest)
override def getResource(resource: Resource, dest: File): Long = get(resource, dest) def setPatterns(): Unit = {
def setPatterns(): Unit = { // done this way for access to protected methods.
// done this way for access to protected methods. setArtifactPatterns(pattern)
setArtifactPatterns(pattern) setIvyPatterns(pattern)
setIvyPatterns(pattern) }
} override protected def findResourceUsingPattern(
override protected def findResourceUsingPattern( mrid: ModuleRevisionId,
mrid: ModuleRevisionId, pattern: String,
pattern: String, artifact: IArtifact,
artifact: IArtifact, rmdparser: ResourceMDParser,
rmdparser: ResourceMDParser, date: Date
date: Date ): ResolvedResource = {
): ResolvedResource = { val extraAttributes =
val extraAttributes = mrid.getExtraAttributes.asScala.toMap.asInstanceOf[Map[String, String]]
mrid.getExtraAttributes.asScala.toMap.asInstanceOf[Map[String, String]] getSbtPluginCrossVersion(extraAttributes) match {
getSbtPluginCrossVersion(extraAttributes) match { case Some(sbtCrossVersion) =>
case Some(sbtCrossVersion) => // if the module is an sbt plugin
// if the module is an sbt plugin // we first try to resolve the artifact with the sbt cross version suffix
// we first try to resolve the artifact with the sbt cross version suffix // and we fallback to the one without the suffix
// and we fallback to the one without the suffix val newArtifact = DefaultArtifact.cloneWithAnotherName(
val newArtifact = DefaultArtifact.cloneWithAnotherName( artifact,
artifact, artifact.getName + sbtCrossVersion
artifact.getName + sbtCrossVersion )
) val resolved =
val resolved = super.findResourceUsingPattern(mrid, pattern, newArtifact, rmdparser, date)
super.findResourceUsingPattern(mrid, pattern, newArtifact, rmdparser, date) if (resolved != null) resolved
if (resolved != null) resolved else super.findResourceUsingPattern(mrid, pattern, artifact, rmdparser, date)
else super.findResourceUsingPattern(mrid, pattern, artifact, rmdparser, date) case None =>
case None => super.findResourceUsingPattern(mrid, pattern, artifact, rmdparser, date)
super.findResourceUsingPattern(mrid, pattern, artifact, rmdparser, date)
}
} }
} }
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 PluginCapableResolver
val resolver = new SshResolver with DescriptorRequired with ThreadSafeSshBasedResolver { if (repo.localIfFile) resolver.setRepository(new LocalIfFileRepo)
override val managedChecksumsEnabled: Boolean = managedChecksums initializeMavenStyle(resolver, repo.name, repo.root)
override def getResource(resource: Resource, dest: File): Long = get(resource, dest) resolver
} .setPatterns() // has to be done after initializeMavenStyle, which calls methods that overwrite the patterns
initializeSSHResolver(resolver, repo, settings) resolver
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
}
} }
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
}
}
} }
private def getSbtPluginCrossVersion(extraAttributes: Map[String, String]): Option[String] = { private def getSbtPluginCrossVersion(extraAttributes: Map[String, String]): Option[String] = {
@ -329,8 +328,9 @@ private[sbt] object ConvertResolver {
override def getDependency(dd: DependencyDescriptor, data: ResolveData) = { override def getDependency(dd: DependencyDescriptor, data: ResolveData) = {
val prev = descriptorString(isAllownomd) val prev = descriptorString(isAllownomd)
setDescriptor(descriptorString(hasExplicitURL(dd))) setDescriptor(descriptorString(hasExplicitURL(dd)))
val t = try super.getDependency(dd, data) val t =
finally setDescriptor(prev) try super.getDependency(dd, data)
finally setDescriptor(prev)
t t
} }
def descriptorString(optional: Boolean) = def descriptorString(optional: Boolean) =

View File

@ -64,7 +64,7 @@ object CustomPomParser {
// Evil hackery to override the default maven pom mappings. // Evil hackery to override the default maven pom mappings.
ReplaceMavenConfigurationMappings.init() 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 InfoKeyPrefix = SbtPomExtraProperties.POM_INFO_KEY_PREFIX
val ApiURLKey = SbtPomExtraProperties.POM_API_KEY val ApiURLKey = SbtPomExtraProperties.POM_API_KEY
val VersionSchemeKey = SbtPomExtraProperties.VERSION_SCHEME_KEY val VersionSchemeKey = SbtPomExtraProperties.VERSION_SCHEME_KEY
@ -75,7 +75,8 @@ object CustomPomParser {
private[this] val unqualifiedKeys = private[this] val unqualifiedKeys =
Set(SbtVersionKey, ScalaVersionKey, ExtraAttributesKey, ApiURLKey, VersionSchemeKey) Set(SbtVersionKey, ScalaVersionKey, ExtraAttributesKey, ApiURLKey, VersionSchemeKey)
/** In the new POM format of sbt plugins, the dependency to an sbt plugin /**
* In the new POM format of sbt plugins, the dependency to an sbt plugin
* contains the sbt cross-version _2.12_1.0. The reason is we want Maven to be able * contains the sbt cross-version _2.12_1.0. The reason is we want Maven to be able
* to resolve the dependency using the pattern: * to resolve the dependency using the pattern:
* <org>/<artifact-name>_2.12_1.0/<version>/<artifact-name>_2.12_1.0-<version>.pom * <org>/<artifact-name>_2.12_1.0/<version>/<artifact-name>_2.12_1.0-<version>.pom
@ -134,7 +135,9 @@ object CustomPomParser {
val MyHash = MakeTransformHash(md) val MyHash = MakeTransformHash(md)
// sbt 0.13.1 used "sbtTransformHash" instead of "e:sbtTransformHash" until #1192 so read both // sbt 0.13.1 used "sbtTransformHash" instead of "e:sbtTransformHash" until #1192 so read both
Option(extraInfo).isDefined && 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 Some(MyHash) => true
case _ => false case _ => false
}) })
@ -297,17 +300,23 @@ object CustomPomParser {
for (l <- md.getLicenses) dmd.addLicense(l) for (l <- md.getLicenses) dmd.addLicense(l)
for ((key, value) <- md.getExtraInfo.asInstanceOf[java.util.Map[String, String]].asScala) for ((key, value) <- md.getExtraInfo.asInstanceOf[java.util.Map[String, String]].asScala)
dmd.addExtraInfo(key, value) dmd.addExtraInfo(key, value)
dmd.addExtraInfo(TransformedHashKey, MakeTransformHash(md)) // mark as transformed by this version, so we don't need to do it again dmd.addExtraInfo(
for ((key, value) <- md.getExtraAttributesNamespaces TransformedHashKey,
.asInstanceOf[java.util.Map[String, String]] MakeTransformHash(md)
.asScala) dmd.addExtraAttributeNamespace(key, value) ) // 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) IvySbt.addExtraNamespace(dmd)
val withExtra = md.getDependencies map { dd => val withExtra = md.getDependencies map { dd =>
addExtra(dd, dependencyExtra) addExtra(dd, dependencyExtra)
} }
val withVersionRangeMod: Seq[DependencyDescriptor] = 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) val unique = IvySbt.mergeDuplicateDefinitions(withVersionRangeMod)
unique foreach dmd.addDependency 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.Resource
import org.apache.ivy.plugins.repository.url.URLResource 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 { private[sbt] object CustomXmlParser extends XmlModuleDescriptorParser {
import XmlModuleDescriptorParser.Parser import XmlModuleDescriptorParser.Parser
class CustomParser(settings: IvySettings, defaultConfig: Option[String]) 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)) 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 setResource(res: Resource): Unit = ()
override def setMd(md: DefaultModuleDescriptor) = { override def setMd(md: DefaultModuleDescriptor) = {
super.setMd(md) super.setMd(md)

View File

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

View File

@ -135,7 +135,8 @@ final class IvySbt(
is is
} }
/** Defines a parallel [[CachedResolutionResolveEngine]]. /**
* Defines a parallel [[CachedResolutionResolveEngine]].
* *
* This is defined here because it needs access to [[mkIvy]]. * This is defined here because it needs access to [[mkIvy]].
*/ */
@ -154,8 +155,10 @@ final class IvySbt(
} }
} }
/** Provides a default ivy implementation that decides which resolution /**
* engine to use depending on the passed ivy configuration options. */ * Provides a default ivy implementation that decides which resolution
* engine to use depending on the passed ivy configuration options.
*/
private class IvyImplementation extends Ivy { private class IvyImplementation extends Ivy {
private val loggerEngine = new SbtMessageLoggerEngine private val loggerEngine = new SbtMessageLoggerEngine
override def getLoggerEngine: SbtMessageLoggerEngine = loggerEngine override def getLoggerEngine: SbtMessageLoggerEngine = loggerEngine
@ -195,7 +198,7 @@ final class IvySbt(
// ========== End Configuration/Setup ============ // ========== End Configuration/Setup ============
/** Uses the configured Ivy instance within a safe context.*/ /** Uses the configured Ivy instance within a safe context. */
def withIvy[T](log: Logger)(f: Ivy => T): T = def withIvy[T](log: Logger)(f: Ivy => T): T =
withIvy(new IvyLoggerInterface(log))(f) withIvy(new IvyLoggerInterface(log))(f)
@ -333,7 +336,7 @@ final class IvySbt(
mod mod
} }
/** Parses the Maven pom 'pomFile' from the given `PomConfiguration`.*/ /** Parses the Maven pom 'pomFile' from the given `PomConfiguration`. */
private def configurePom(pc: PomConfiguration) = { private def configurePom(pc: PomConfiguration) = {
val md = CustomPomParser.default.parseDescriptor(settings, toURL(pc.file), pc.validate) val md = CustomPomParser.default.parseDescriptor(settings, toURL(pc.file), pc.validate)
val dmd = IvySbt.toDefaultModuleDescriptor(md) val dmd = IvySbt.toDefaultModuleDescriptor(md)
@ -347,7 +350,7 @@ final class IvySbt(
(dmd, defaultConf) (dmd, defaultConf)
} }
/** Parses the Ivy file 'ivyFile' from the given `IvyFileConfiguration`.*/ /** Parses the Ivy file 'ivyFile' from the given `IvyFileConfiguration`. */
private def configureIvyFile(ifc: IvyFileConfiguration) = { private def configureIvyFile(ifc: IvyFileConfiguration) = {
val parser = new CustomXmlParser.CustomParser(settings, None) val parser = new CustomXmlParser.CustomParser(settings, None)
parser.setValidate(ifc.validate) parser.setValidate(ifc.validate)
@ -703,7 +706,7 @@ private[sbt] object IvySbt {
moduleID.addConflictManager(mid, matcher, manager) moduleID.addConflictManager(mid, matcher, manager)
} }
/** Converts the given sbt module id into an Ivy ModuleRevisionId.*/ /** Converts the given sbt module id into an Ivy ModuleRevisionId. */
def toID(m: ModuleID) = { def toID(m: ModuleID) = {
import m._ import m._
ModuleRevisionId.newInstance( ModuleRevisionId.newInstance(
@ -783,7 +786,8 @@ private[sbt] object IvySbt {
} }
private[sbt] def javaMap(m: Map[String, String], unqualify: Boolean = false) = { private[sbt] def javaMap(m: Map[String, String], unqualify: Boolean = false) = {
import scala.collection.JavaConverters._ import scala.collection.JavaConverters._
val map = if (unqualify) m map { case (k, v) => (k.stripPrefix("e:"), v) } else m val map = if (unqualify) m map { case (k, v) => (k.stripPrefix("e:"), v) }
else m
if (map.isEmpty) null else map.asJava if (map.isEmpty) null else map.asJava
} }
@ -814,8 +818,8 @@ private[sbt] object IvySbt {
elem: scala.xml.Elem, elem: scala.xml.Elem,
extra: Map[String, String] extra: Map[String, String]
): scala.xml.Elem = ): scala.xml.Elem =
extra.foldLeft(elem) { extra.foldLeft(elem) { case (e, (key, value)) =>
case (e, (key, value)) => e % new scala.xml.UnprefixedAttribute(key, value, scala.xml.Null) e % new scala.xml.UnprefixedAttribute(key, value, scala.xml.Null)
} }
private def hasInfo(module: ModuleID, x: scala.xml.NodeSeq) = { private def hasInfo(module: ModuleID, x: scala.xml.NodeSeq) = {
val info = <g>{x}</g> \ "info" val info = <g>{x}</g> \ "info"
@ -943,7 +947,7 @@ private[sbt] object IvySbt {
} }
} }
/** Transforms an sbt ModuleID into an Ivy DefaultDependencyDescriptor.*/ /** Transforms an sbt ModuleID into an Ivy DefaultDependencyDescriptor. */
def convertDependency( def convertDependency(
moduleID: DefaultModuleDescriptor, moduleID: DefaultModuleDescriptor,
dependency: ModuleID, dependency: ModuleID,
@ -961,7 +965,9 @@ private[sbt] object IvySbt {
dependency.configurations match { dependency.configurations match {
case None => // The configuration for this dependency was not explicitly specified, so use the default case None => // The configuration for this dependency was not explicitly specified, so use the default
parser.parseDepsConfs(parser.getDefaultConf, dependencyDescriptor) parser.parseDepsConfs(parser.getDefaultConf, dependencyDescriptor)
case Some(confs) => // The configuration mapping (looks like: test->default) was specified for this dependency case Some(
confs
) => // The configuration mapping (looks like: test->default) was specified for this dependency
parser.parseDepsConfs(confs, dependencyDescriptor) parser.parseDepsConfs(confs, dependencyDescriptor)
} }
for (artifact <- dependency.explicitArtifacts) { for (artifact <- dependency.explicitArtifacts) {

View File

@ -29,7 +29,7 @@ import sbt.internal.librarymanagement.IvyUtil.TransientNetworkException
object IvyActions { 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 = { def install(module: IvySbt#Module, from: String, to: String, log: Logger): Unit = {
module.withModule(log) { (ivy, md, _) => module.withModule(log) { (ivy, md, _) =>
for (dependency <- md.getDependencies) { for (dependency <- md.getDependencies) {
@ -57,7 +57,7 @@ object IvyActions {
module.owner.cleanCachedResolutionCache() 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 = { def makePomFile(module: IvySbt#Module, configuration: MakePomConfiguration, log: Logger): File = {
import configuration.{ import configuration.{
allRepositories, allRepositories,
@ -91,13 +91,12 @@ object IvyActions {
val deliverIvyPattern = configuration.deliverIvyPattern val deliverIvyPattern = configuration.deliverIvyPattern
.getOrElse(sys.error("deliverIvyPattern must be specified.")) .getOrElse(sys.error("deliverIvyPattern must be specified."))
val status = getDeliverStatus(configuration.status) val status = getDeliverStatus(configuration.status)
module.withModule(log) { module.withModule(log) { case (ivy, md, _) =>
case (ivy, md, _) => val revID = md.getModuleRevisionId
val revID = md.getModuleRevisionId val options = DeliverOptions.newInstance(ivy.getSettings).setStatus(status)
val options = DeliverOptions.newInstance(ivy.getSettings).setStatus(status) options.setConfs(getConfigurations(md, configuration.configurations))
options.setConfs(getConfigurations(md, configuration.configurations)) ivy.deliver(revID, revID.getRevision, deliverIvyPattern, options)
ivy.deliver(revID, revID.getRevision, deliverIvyPattern, options) deliveredFile(ivy, deliverIvyPattern, md)
deliveredFile(ivy, deliverIvyPattern, md)
} }
} }
@ -130,18 +129,17 @@ object IvyActions {
val artifacts = Map(configuration.artifacts: _*) val artifacts = Map(configuration.artifacts: _*)
val checksums = configuration.checksums val checksums = configuration.checksums
module.withModule(log) { module.withModule(log) { case (ivy, md, _) =>
case (ivy, md, _) => val resolver = ivy.getSettings.getResolver(resolverName)
val resolver = ivy.getSettings.getResolver(resolverName) if (resolver eq null) sys.error("Undefined resolver '" + resolverName + "'")
if (resolver eq null) sys.error("Undefined resolver '" + resolverName + "'") val ivyArtifact = ivyFile map { file =>
val ivyArtifact = ivyFile map { file => (MDArtifact.newIvyArtifact(md), file)
(MDArtifact.newIvyArtifact(md), file) }
} val cross = crossVersionMap(module.moduleSettings)
val cross = crossVersionMap(module.moduleSettings) val as = mapArtifacts(md, cross, artifacts) ++ ivyArtifact.toList
val as = mapArtifacts(md, cross, artifacts) ++ ivyArtifact.toList withChecksums(resolver, checksums) {
withChecksums(resolver, checksums) { publish(md, as, resolver, overwrite = configuration.overwrite)
publish(md, as, resolver, overwrite = configuration.overwrite) }
}
} }
} }
private[this] def withChecksums[T](resolver: DependencyResolver, checksums: Vector[String])( private[this] def withChecksums[T](resolver: DependencyResolver, checksums: Vector[String])(
@ -193,35 +191,36 @@ object IvyActions {
uwconfig: UnresolvedWarningConfiguration, uwconfig: UnresolvedWarningConfiguration,
log: Logger log: Logger
): Either[UnresolvedWarning, UpdateReport] = { ): Either[UnresolvedWarning, UpdateReport] = {
module.withModule(log) { module.withModule(log) { case (ivy, moduleDescriptor, _) =>
case (ivy, moduleDescriptor, _) => // Warn about duplicated and inconsistent dependencies
// Warn about duplicated and inconsistent dependencies val iw = IvySbt.inconsistentDuplicateWarning(moduleDescriptor)
val iw = IvySbt.inconsistentDuplicateWarning(moduleDescriptor) iw.foreach(log.warn(_))
iw.foreach(log.warn(_))
val metadataDirectory = configuration.metadataDirectory val metadataDirectory = configuration.metadataDirectory
// Create inputs, resolve and retrieve the module descriptor // Create inputs, resolve and retrieve the module descriptor
val inputs = ResolutionInputs(ivy, moduleDescriptor, configuration, log) val inputs = ResolutionInputs(ivy, moduleDescriptor, configuration, log)
val resolutionResult: Either[ResolveException, UpdateReport] = { val resolutionResult: Either[ResolveException, UpdateReport] = {
if (module.owner.configuration.updateOptions.cachedResolution && metadataDirectory.isDefined) { if (
val cache = module.owner.configuration.updateOptions.cachedResolution && metadataDirectory.isDefined
metadataDirectory.getOrElse(sys.error("Missing directory for cached resolution.")) ) {
cachedResolveAndRetrieve(inputs, cache) val cache =
} else resolveAndRetrieve(inputs) metadataDirectory.getOrElse(sys.error("Missing directory for cached resolution."))
} cachedResolveAndRetrieve(inputs, cache)
} else resolveAndRetrieve(inputs)
}
// Convert to unresolved warning or retrieve update report // Convert to unresolved warning or retrieve update report
resolutionResult.fold( resolutionResult.fold(
exception => Left(UnresolvedWarning(exception, uwconfig)), exception => Left(UnresolvedWarning(exception, uwconfig)),
ur0 => { ur0 => {
val ur = configuration.retrieveManaged match { val ur = configuration.retrieveManaged match {
case Some(retrieveConf) => retrieve(log, ivy, ur0, retrieveConf) case Some(retrieveConf) => retrieve(log, ivy, ur0, retrieveConf)
case _ => ur0 case _ => ur0
}
Right(ur)
} }
) Right(ur)
}
)
} }
} }
@ -252,11 +251,10 @@ object IvyActions {
exclude.getOrElse(restrictedCopy(id, false), Set.empty[String]) exclude.getOrElse(restrictedCopy(id, false), Set.empty[String])
def extractExcludes(report: UpdateReport): Map[ModuleID, Set[String]] = def extractExcludes(report: UpdateReport): Map[ModuleID, Set[String]] =
report.allMissing flatMap { report.allMissing flatMap { case (_, mod, art) =>
case (_, mod, art) => art.classifier.map { c =>
art.classifier.map { c => (restrictedCopy(mod, false), c)
(restrictedCopy(mod, false), c) }
}
} groupBy (_._1) map { case (mod, pairs) => (mod, pairs.map(_._2).toSet) } } 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 { implicit def toIvyFilter(f: ArtifactTypeFilter): IvyFilter = new IvyFilter {
override def accept(o: Object): Boolean = Option(o) exists { override def accept(o: Object): Boolean = Option(o) exists { case a: IArtifact =>
case a: IArtifact => applyFilter(a) applyFilter(a)
} }
def applyFilter(a: IArtifact): Boolean = def applyFilter(a: IArtifact): Boolean =
@ -498,13 +496,12 @@ object IvyActions {
checkFilesPresent(artifacts) checkFilesPresent(artifacts)
try { try {
resolver.beginPublishTransaction(module.getModuleRevisionId(), overwrite); resolver.beginPublishTransaction(module.getModuleRevisionId(), overwrite);
artifacts.foreach { artifacts.foreach { case (artifact, file) =>
case (artifact, file) => IvyUtil.retryWithBackoff(
IvyUtil.retryWithBackoff( resolver.publish(artifact, file, overwrite),
resolver.publish(artifact, file, overwrite), TransientNetworkException.apply,
TransientNetworkException.apply, maxAttempts = LMSysProp.maxPublishAttempts
maxAttempts = LMSysProp.maxPublishAttempts )
)
} }
resolver.commitPublishTransaction() resolver.commitPublishTransaction()
} catch { } 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]) { class IvyCache(val ivyHome: Option[File]) {
def lockFile = new File(ivyHome getOrElse Path.userHome, ".sbt.cache.lock") 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( def cacheJar(
moduleID: ModuleID, moduleID: ModuleID,
file: File, 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 = { def clearCachedJar(id: ModuleID, lock: Option[xsbti.GlobalLock], log: Logger): Unit = {
try { try {
withCachedJar(id, lock, log)(_.delete); () 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( def retrieveCachedJar(
id: ModuleID, id: ModuleID,
toDirectory: File, toDirectory: File,
@ -74,7 +74,7 @@ class IvyCache(val ivyHome: Option[File]) {
copyTo 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)( def withCachedJar[T](id: ModuleID, lock: Option[xsbti.GlobalLock], log: Logger)(
f: File => T f: File => T
): T = { ): T = {
@ -89,7 +89,7 @@ class IvyCache(val ivyHome: Option[File]) {
if (cachedFile.exists) f(cachedFile) else throw new NotInCache(id) 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)( def withDefaultCache[T](lock: Option[xsbti.GlobalLock], log: Logger)(
f: DefaultRepositoryCacheManager => T f: DefaultRepositoryCacheManager => T
): T = { ): T = {
@ -103,7 +103,7 @@ class IvyCache(val ivyHome: Option[File]) {
} }
private def unknownOrigin(artifact: IvyArtifact) = ArtifactOrigin.unkwnown(artifact) 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) = { private def basicLocalIvy(lock: Option[xsbti.GlobalLock], log: Logger) = {
val local = Resolver.defaultLocal val local = Resolver.defaultLocal
val paths = IvyPaths(new File("."), ivyHome) val paths = IvyPaths(new File("."), ivyHome)
@ -115,12 +115,12 @@ class IvyCache(val ivyHome: Option[File]) {
(new IvySbt(conf), local) (new IvySbt(conf), 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 = private def defaultArtifact(moduleID: ModuleID): IvyArtifact =
new DefaultArtifact(IvySbt.toID(moduleID), null, moduleID.name, "jar", "jar") 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 { private class FileDownloader extends ResourceDownloader {
def download(artifact: IvyArtifact, resource: Resource, dest: File): Unit = { def download(artifact: IvyArtifact, resource: Resource, dest: File): Unit = {
if (dest.exists()) dest.delete() 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) 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 // TODO: provide access to this information some other way
def debug(msg: String): Unit = () def debug(msg: String): Unit = ()
def verbose(msg: String): Unit = logger.verbose(msg) def verbose(msg: String): Unit = logger.verbose(msg)

View File

@ -54,14 +54,18 @@ object IvyRetrieve {
private[sbt] def organizationArtifactReports( private[sbt] def organizationArtifactReports(
confReport: ConfigurationResolveReport confReport: ConfigurationResolveReport
): Vector[OrganizationArtifactReport] = { ): Vector[OrganizationArtifactReport] = {
val moduleIds = confReport.getModuleIds.toArray.toVector collect { val moduleIds = confReport.getModuleIds.toArray.toVector collect { case mId: IvyModuleId =>
case mId: IvyModuleId => mId mId
} }
def organizationArtifact(mid: IvyModuleId): OrganizationArtifactReport = { def organizationArtifact(mid: IvyModuleId): OrganizationArtifactReport = {
val deps = confReport.getNodes(mid).toArray.toVector collect { case node: IvyNode => node } val deps = confReport.getNodes(mid).toArray.toVector collect { case node: IvyNode => node }
OrganizationArtifactReport(mid.getOrganisation, mid.getName, deps map { OrganizationArtifactReport(
moduleRevisionDetail(confReport, _) mid.getOrganisation,
}) mid.getName,
deps map {
moduleRevisionDetail(confReport, _)
}
)
} }
moduleIds map { organizationArtifact } moduleIds map { organizationArtifact }
} }
@ -141,9 +145,13 @@ object IvyRetrieve {
val edOpt = Option(dep.getEvictedData(confReport.getConfiguration)) val edOpt = Option(dep.getEvictedData(confReport.getConfiguration))
edOpt match { edOpt match {
case Some(ed) => case Some(ed) =>
(true, nonEmptyString(Option(ed.getConflictManager) map { _.toString } getOrElse { (
"transitive" true,
}), nonEmptyString(ed.getDetail)) nonEmptyString(Option(ed.getConflictManager) map { _.toString } getOrElse {
"transitive"
}),
nonEmptyString(ed.getDetail)
)
case None => (true, None, None) case None => (true, None, None)
} }
case _ => (false, None, None) case _ => (false, None, None)

View File

@ -67,9 +67,11 @@ object IvyScalaUtil {
new NamespaceTransformer { new NamespaceTransformer {
def transform(mrid: ModuleRevisionId): ModuleRevisionId = { def transform(mrid: ModuleRevisionId): ModuleRevisionId = {
if (mrid == null) mrid if (mrid == null) mrid
else if ((isScala2Artifact(mrid.getName) || isScala3Artifact(mrid.getName)) && else if (
configQualifies && (isScala2Artifact(mrid.getName) || isScala3Artifact(mrid.getName)) &&
dependeeQualifies) { configQualifies &&
dependeeQualifies
) {
// do not override the binary incompatible Scala version because: // do not override the binary incompatible Scala version because:
// - the artifacts compiled with Scala 3 depends on the Scala 2.13 scala-library // - 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 // - 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")) .forall(bv => bv.startsWith("3") || bv.startsWith("2.13"))
def matchesOneOfTheConfigs = dep.getModuleConfigurations exists { scalaVersionConfigs } def matchesOneOfTheConfigs = dep.getModuleConfigurations exists { scalaVersionConfigs }
val mismatched = isScalaLangOrg && isScalaArtifact && hasBinVerMismatch && matchesOneOfTheConfigs val mismatched =
isScalaLangOrg && isScalaArtifact && hasBinVerMismatch && matchesOneOfTheConfigs
if (mismatched) if (mismatched)
Some( Some(
"Binary version (" + depBinaryVersion + ") for dependency " + id + "Binary version (" + depBinaryVersion + ") for dependency " + id +

View File

@ -102,5 +102,6 @@ private[sbt] object ResolutionCache {
private val Name = "sbt-resolution-cache" 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 // 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

@ -105,7 +105,7 @@ private[sbt] class CachedResolutionResolveCache {
s"""Include(${rule.getId},${rule.getConfigurations.mkString(",")},${rule.getMatcher})""" s"""Include(${rule.getId},${rule.getConfigurations.mkString(",")},${rule.getMatcher})"""
def artifactString(dad: DependencyArtifactDescriptor): String = def artifactString(dad: DependencyArtifactDescriptor): String =
s"""Artifact(${dad.getName},${dad.getType},${dad.getExt},${dad.getUrl},${dad.getConfigurations s"""Artifact(${dad.getName},${dad.getType},${dad.getExt},${dad.getUrl},${dad.getConfigurations
.mkString(",")},${dad.getExtraAttributes})""" .mkString(",")},${dad.getExtraAttributes})"""
val mrid = dd.getDependencyRevisionId val mrid = dd.getDependencyRevisionId
val confMap = (dd.getModuleConfigurations map { conf => val confMap = (dd.getModuleConfigurations map { conf =>
conf + "->(" + dd.getDependencyConfigurations(conf).mkString(",") + ")" conf + "->(" + dd.getDependencyConfigurations(conf).mkString(",") + ")"
@ -127,9 +127,13 @@ private[sbt] class CachedResolutionResolveCache {
val mesStr = (mes map excludeRuleString).mkString(",") val mesStr = (mes map excludeRuleString).mkString(",")
val os = extractOverrides(parent) val os = extractOverrides(parent)
val moduleLevel = s"""dependencyOverrides=${os.mkString(",")};moduleExclusions=$mesStr""" val moduleLevel = s"""dependencyOverrides=${os.mkString(",")};moduleExclusions=$mesStr"""
val depsString = s"""$mrid;${confMap.mkString(",")};isForce=${dd.isForce};isChanging=${dd.isChanging};isTransitive=${dd.isTransitive};""" + val depsString = s"""$mrid;${confMap.mkString(
s"""exclusions=${exclusions.mkString(",")};inclusions=${inclusions.mkString(",")};explicitArtifacts=${explicitArtifacts ","
.mkString(",")};$moduleLevel;""" )};isForce=${dd.isForce};isChanging=${dd.isChanging};isTransitive=${dd.isTransitive};""" +
s"""exclusions=${exclusions.mkString(",")};inclusions=${inclusions.mkString(
","
)};explicitArtifacts=${explicitArtifacts
.mkString(",")};$moduleLevel;"""
val sha1 = Hash.toHex( val sha1 = Hash.toHex(
Hash(s"""graphVersion=${CachedResolutionResolveCache.graphVersion};$depsString""") Hash(s"""graphVersion=${CachedResolutionResolveCache.graphVersion};$depsString""")
) )
@ -158,15 +162,14 @@ private[sbt] class CachedResolutionResolveCache {
md0.getAllDependencyDescriptorMediators.getAllRules.asScala.toSeq.toVector sortBy { md0.getAllDependencyDescriptorMediators.getAllRules.asScala.toSeq.toVector sortBy {
case (k, _) => case (k, _) =>
k.toString k.toString
} collect { } collect { case (k: MapMatcher, v: OverrideDependencyDescriptorMediator) =>
case (k: MapMatcher, v: OverrideDependencyDescriptorMediator) => val attr: Map[Any, Any] = k.getAttributes.asScala.toMap
val attr: Map[Any, Any] = k.getAttributes.asScala.toMap val module = IvyModuleId.newInstance(
val module = IvyModuleId.newInstance( attr(IvyPatternHelper.ORGANISATION_KEY).toString,
attr(IvyPatternHelper.ORGANISATION_KEY).toString, attr(IvyPatternHelper.MODULE_KEY).toString
attr(IvyPatternHelper.MODULE_KEY).toString )
) val pm = k.getPatternMatcher
val pm = k.getPatternMatcher IvyOverride(module, pm, v)
IvyOverride(module, pm, v)
} }
} }
def getOrElseUpdateMiniGraph( def getOrElseUpdateMiniGraph(
@ -200,8 +203,10 @@ private[sbt] class CachedResolutionResolveCache {
} }
val staticGraphDirectory = miniGraphPath / "static" val staticGraphDirectory = miniGraphPath / "static"
val dynamicGraphDirectory = miniGraphPath / "dynamic" val dynamicGraphDirectory = miniGraphPath / "dynamic"
val staticGraphPath = staticGraphDirectory / pathScalaVersion / pathSbtVersion / pathOrg / pathName / pathRevision / "graphs" / "graph.json" val staticGraphPath =
val dynamicGraphPath = dynamicGraphDirectory / todayStr / logicalClock.toString / pathScalaVersion / pathSbtVersion / pathOrg / pathName / pathRevision / "graphs" / "graph.json" 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 = { def cleanDynamicGraph(): Unit = {
val list = IO.listFiles(dynamicGraphDirectory, DirectoryFilter).toList val list = IO.listFiles(dynamicGraphDirectory, DirectoryFilter).toList
list filterNot { d => list filterNot { d =>
@ -282,9 +287,12 @@ private[sbt] class CachedResolutionResolveCache {
val moduleIdMap = Map(conflicts map { x => val moduleIdMap = Map(conflicts map { x =>
x.module -> 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 { (conflictCache get ((cf0, cf1))) match {
case Some((surviving, evicted, mgr)) => reconstructReports(surviving, evicted, mgr) case Some((surviving, evicted, mgr)) => reconstructReports(surviving, evicted, mgr)
@ -410,59 +418,58 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
Left(new ResolveException(messages, failed, failedPaths)) Left(new ResolveException(messages, failed, failedPaths))
} }
} }
val (internal, external) = mds.partition { val (internal, external) = mds.partition { case (_, _, dd) =>
case (_, _, dd) => cache.internalDependency(dd, projectResolver).isDefined cache.internalDependency(dd, projectResolver).isDefined
} }
val internalResults = internal map { val internalResults = internal map { case (md, changing, dd) =>
case (md, changing, dd) => cache.getOrElseUpdateMiniGraph(
cache.getOrElseUpdateMiniGraph( md,
md, changing,
changing, logicalClock,
logicalClock, miniGraphPath,
miniGraphPath, cachedDescriptor,
cachedDescriptor, log
log ) {
) { doWork(md, dd)
doWork(md, dd) }
}
} }
val externalResults = external map { val externalResults = external map { case (md0, changing, dd) =>
case (md0, changing, dd) => val configurationsInInternal = internalResults flatMap {
val configurationsInInternal = internalResults flatMap { case Right(ur) =>
case Right(ur) => ur.allModules.flatMap { case md =>
ur.allModules.flatMap { val sameName = md.name == dd.getDependencyId.getName
case md => val sameOrg = md.organization == dd.getDependencyId.getOrganisation
val sameName = md.name == dd.getDependencyId.getName if (sameName && sameOrg) md.configurations
val sameOrg = md.organization == dd.getDependencyId.getOrganisation else None
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 _ => ()
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 _ => () cache.getOrElseUpdateMiniGraph(
} md0,
changing,
cache.getOrElseUpdateMiniGraph( logicalClock,
md0, miniGraphPath,
changing, cachedDescriptor,
logicalClock, log
miniGraphPath, ) {
cachedDescriptor, doWork(md0, dd)
log }
) {
doWork(md0, dd)
}
} }
val results = internalResults ++ externalResults val results = internalResults ++ externalResults
val uReport = val uReport =
@ -485,21 +492,20 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
log: Logger log: Logger
): Either[ResolveException, UpdateReport] = ): Either[ResolveException, UpdateReport] =
if (!missingOk && (results exists { _.isLeft })) 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)) else Right(mergeReports(md0, results collect { case Right(ur) => ur }, resolveTime, os, log))
def mergeErrors(md0: ModuleDescriptor, errors: Vector[ResolveException]): ResolveException = { def mergeErrors(md0: ModuleDescriptor, errors: Vector[ResolveException]): ResolveException = {
val messages = errors flatMap { _.messages } val messages = errors flatMap { _.messages }
val failed = errors flatMap { _.failed } val failed = errors flatMap { _.failed }
val failedPaths = errors flatMap { val failedPaths = errors flatMap {
_.failedPaths.toList map { _.failedPaths.toList map { case (failed, paths) =>
case (failed, paths) => if (paths.isEmpty) (failed, paths)
if (paths.isEmpty) (failed, paths) else
else (
( failed,
failed, List(IvyRetrieve.toModuleID(md0.getResolvedModuleRevisionId)) ::: paths.toList.tail
List(IvyRetrieve.toModuleID(md0.getResolvedModuleRevisionId)) ::: paths.toList.tail )
)
} }
} }
new ResolveException(messages, failed, ListMap(failedPaths: _*)) new ResolveException(messages, failed, ListMap(failedPaths: _*))
@ -579,12 +585,11 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
// this might take up some memory, but it's limited to a single // this might take up some memory, but it's limited to a single
val reports1 = reports0 flatMap { filterReports } val reports1 = reports0 flatMap { filterReports }
val allModules0: Map[(String, String), Vector[OrganizationArtifactReport]] = val allModules0: Map[(String, String), Vector[OrganizationArtifactReport]] =
Map(orgNamePairs map { Map(orgNamePairs map { case (organization, name) =>
case (organization, name) => val xs = reports1 filter { oar =>
val xs = reports1 filter { oar => oar.organization == organization && oar.name == name
oar.organization == organization && oar.name == name }
} ((organization, name), xs)
((organization, name), xs)
}: _*) }: _*)
// this returns a List of Lists of (org, name). should be deterministic // this returns a List of Lists of (org, name). should be deterministic
def detectLoops( def detectLoops(
@ -766,8 +771,8 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
val completelyEvicted = xs forall { _.evicted } val completelyEvicted = xs forall { _.evicted }
val allCallers = xs flatMap { _.callers } 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. // 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 { val distinctByModuleId = allCallers.groupBy({ _.caller }).toVector map { case (_, xs) =>
case (_, xs) => xs.head xs.head
} }
val allArtifacts = (xs flatMap { _.artifacts }).distinct val allArtifacts = (xs flatMap { _.artifacts }).distinct
xs.head xs.head
@ -777,10 +782,9 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
} }
val merged = (modules groupBy { m => val merged = (modules groupBy { m =>
(m.module.organization, m.module.name, m.module.revision) (m.module.organization, m.module.name, m.module.revision)
}).toSeq.toVector flatMap { }).toSeq.toVector flatMap { case (_, xs) =>
case (_, xs) => if (xs.size < 2) xs
if (xs.size < 2) xs else Vector(mergeModuleReports(xs))
else Vector(mergeModuleReports(xs))
} }
val conflicts = merged filter { m => val conflicts = merged filter { m =>
!m.evicted && m.problem.isEmpty !m.evicted && m.problem.isEmpty
@ -789,9 +793,12 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
else else
resolveConflict(rootModuleConf, conflicts, os, log) match { resolveConflict(rootModuleConf, conflicts, os, log) match {
case (survivor, evicted) => case (survivor, evicted) =>
(survivor ++ (merged filter { m => (
m.evicted || m.problem.isDefined survivor ++ (merged filter { m =>
}), evicted) m.evicted || m.problem.isDefined
}),
evicted
)
} }
} }
@ -869,9 +876,13 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
}) match { }) match {
case Some(m) => case Some(m) =>
log.debug(s"- directly forced dependency: $m ${m.callers}") log.debug(s"- directly forced dependency: $m ${m.callers}")
(Vector(m), conflicts filterNot { _ == m } map { (
_.withEvicted(true).withEvictedReason(Some("direct-force")) Vector(m),
}, "direct-force") conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some("direct-force"))
},
"direct-force"
)
case None => case None =>
(conflicts find { m => (conflicts find { m =>
m.callers.exists { _.isForceDependency } m.callers.exists { _.isForceDependency }
@ -879,18 +890,26 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
// Ivy translates pom.xml dependencies to forced="true", so transitive force is broken. // Ivy translates pom.xml dependencies to forced="true", so transitive force is broken.
case Some(m) if !ignoreTransitiveForce => case Some(m) if !ignoreTransitiveForce =>
log.debug(s"- transitively forced dependency: $m ${m.callers}") log.debug(s"- transitively forced dependency: $m ${m.callers}")
(Vector(m), conflicts filterNot { _ == m } map { (
_.withEvicted(true).withEvictedReason(Some("transitive-force")) Vector(m),
}, "transitive-force") conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some("transitive-force"))
},
"transitive-force"
)
case _ => case _ =>
val strategy = lcm.getStrategy val strategy = lcm.getStrategy
val infos = conflicts map { ModuleReportArtifactInfo(_) } val infos = conflicts map { ModuleReportArtifactInfo(_) }
log.debug(s"- Using $strategy with $infos") log.debug(s"- Using $strategy with $infos")
Option(strategy.findLatest(infos.toArray, None.orNull)) match { Option(strategy.findLatest(infos.toArray, None.orNull)) match {
case Some(ModuleReportArtifactInfo(m)) => case Some(ModuleReportArtifactInfo(m)) =>
(Vector(m), conflicts filterNot { _ == m } map { (
_.withEvicted(true).withEvictedReason(Some(lcm.toString)) Vector(m),
}, lcm.toString) conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some(lcm.toString))
},
lcm.toString
)
case _ => (conflicts, Vector(), lcm.toString) case _ => (conflicts, Vector(), lcm.toString)
} }
} }
@ -905,9 +924,13 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
mr.module.revision == ovrVersion mr.module.revision == ovrVersion
} match { } match {
case Some(m) => case Some(m) =>
(Vector(m), conflicts filterNot { _ == m } map { (
_.withEvicted(true).withEvictedReason(Some("override")) Vector(m),
}, "override") conflicts filterNot { _ == m } map {
_.withEvicted(true).withEvictedReason(Some("override"))
},
"override"
)
case None => case None =>
sys.error( sys.error(
s"override dependency specifies $ovrVersion but no candidates were found: " + (conflicts map { s"override dependency specifies $ovrVersion but no candidates were found: " + (conflicts map {
@ -925,7 +948,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
}).mkString("(", ", ", ")")) }).mkString("(", ", ", ")"))
) )
case lcm: LatestConflictManager => useLatest(lcm) 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) { if (conflicts.size == 2 && os.isEmpty) {

View File

@ -64,10 +64,14 @@ object ErrorMessageAuthenticator {
ivyOriginalField.set(ivy, newOriginal) ivyOriginalField.set(ivy, newOriginal)
} }
try Option(ivyOriginalField.get(ivy).asInstanceOf[Authenticator]) match { try
case Some(_: ErrorMessageAuthenticator) => // We're already installed, no need to do the work again. Option(ivyOriginalField.get(ivy).asInstanceOf[Authenticator]) match {
case originalOpt => installIntoIvyImpl(originalOpt) case Some(
} catch { _: ErrorMessageAuthenticator
) => // We're already installed, no need to do the work again.
case originalOpt => installIntoIvyImpl(originalOpt)
}
catch {
case t: Throwable => case t: Throwable =>
Message.debug( Message.debug(
"Error occurred while trying to install debug messages into Ivy Authentication" + t.getMessage "Error occurred while trying to install debug messages into Ivy Authentication" + t.getMessage
@ -135,16 +139,17 @@ private[sbt] final class ErrorMessageAuthenticator(original: Option[Authenticato
// Grabs the authentication that would have been provided had we not been installed... // Grabs the authentication that would have been provided had we not been installed...
def originalAuthentication: Option[PasswordAuthentication] = { def originalAuthentication: Option[PasswordAuthentication] = {
Authenticator.setDefault(original.orNull) Authenticator.setDefault(original.orNull)
try Option( try
Authenticator.requestPasswordAuthentication( Option(
getRequestingHost, Authenticator.requestPasswordAuthentication(
getRequestingSite, getRequestingHost,
getRequestingPort, getRequestingSite,
getRequestingProtocol, getRequestingPort,
getRequestingPrompt, getRequestingProtocol,
getRequestingScheme getRequestingPrompt,
getRequestingScheme
)
) )
)
finally Authenticator.setDefault(this) finally Authenticator.setDefault(this)
} }
originalAuthentication.orNull originalAuthentication.orNull

View File

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

View File

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

View File

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

View File

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

View File

@ -16,11 +16,11 @@ object Credentials {
def apply(file: File): Credentials = def apply(file: File): Credentials =
new FileCredentials(file) new FileCredentials(file)
/** Add the provided credentials to Ivy's credentials cache.*/ /** Add the provided credentials to Ivy's credentials cache. */
def add(realm: String, host: String, userName: String, passwd: String): Unit = def add(realm: String, host: String, userName: String, passwd: String): Unit =
CredentialsStore.INSTANCE.addCredentials(realm, host, userName, passwd) CredentialsStore.INSTANCE.addCredentials(realm, host, userName, passwd)
/** Load credentials from the given file into Ivy's credentials cache.*/ /** Load credentials from the given file into Ivy's credentials cache. */
def add(path: File, log: Logger): Unit = def add(path: File, log: Logger): Unit =
loadCredentials(path) match { loadCredentials(path) match {
case Left(err) => log.warn(err) case Left(err) => log.warn(err)

View File

@ -79,12 +79,12 @@ final class UpdateOptions private[sbt] (
override def equals(o: Any): Boolean = o match { override def equals(o: Any): Boolean = o match {
case o: UpdateOptions => case o: UpdateOptions =>
this.circularDependencyLevel == o.circularDependencyLevel && this.circularDependencyLevel == o.circularDependencyLevel &&
this.interProjectFirst == o.interProjectFirst && this.interProjectFirst == o.interProjectFirst &&
this.latestSnapshots == o.latestSnapshots && this.latestSnapshots == o.latestSnapshots &&
this.cachedResolution == o.cachedResolution && this.cachedResolution == o.cachedResolution &&
this.gigahorse == o.gigahorse && this.gigahorse == o.gigahorse &&
this.resolverConverter == o.resolverConverter && this.resolverConverter == o.resolverConverter &&
this.moduleResolvers == o.moduleResolvers this.moduleResolvers == o.moduleResolvers
case _ => false case _ => false
} }

View File

@ -121,7 +121,7 @@ object ComponentManagerTest extends BasicTestSuite {
TestLogger { logger => TestLogger { logger =>
withTemporaryDirectory { temp => withTemporaryDirectory { temp =>
// The actual classes we'll use at runtime. // The actual classes we'll use at runtime.
//val mgr = new ComponentManager(xsbt.boot.Locks, new xsbt.boot.ComponentProvider(temp, true), Some(ivyHome), logger) // val mgr = new ComponentManager(xsbt.boot.Locks, new xsbt.boot.ComponentProvider(temp, true), Some(ivyHome), logger)
// A stub component manager // A stub component manager
object provider extends ComponentProvider { object provider extends ComponentProvider {

View File

@ -28,12 +28,22 @@ class CredentialsSpec extends AnyFunSuite {
test("DirectCredentials.toString") { test("DirectCredentials.toString") {
assert( assert(
Credentials(realm = null, host = "example.org", userName = "username", passwd = "password").toString == Credentials(
realm = null,
host = "example.org",
userName = "username",
passwd = "password"
).toString ==
"""DirectCredentials(null, "example.org", "username", ****)""" """DirectCredentials(null, "example.org", "username", ****)"""
) )
assert( assert(
Credentials(realm = "realm", host = "example.org", userName = "username", passwd = "password").toString == Credentials(
realm = "realm",
host = "example.org",
userName = "username",
passwd = "password"
).toString ==
"""DirectCredentials("realm", "example.org", "username", ****)""" """DirectCredentials("realm", "example.org", "username", ****)"""
) )
} }

View File

@ -118,11 +118,17 @@ object EvictionErrorSpec extends BaseIvySpecification {
def oldAkkaPvp = List("com.typesafe.akka" % "*" % "pvp") def oldAkkaPvp = List("com.typesafe.akka" % "*" % "pvp")
lazy val `akkaActor2.1.4` = lazy val `akkaActor2.1.4` =
ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(Some("compile")) cross CrossVersion.binary ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(
Some("compile")
) cross CrossVersion.binary
lazy val `akkaActor2.3.0` = lazy val `akkaActor2.3.0` =
ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("compile")) cross CrossVersion.binary ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(
Some("compile")
) cross CrossVersion.binary
lazy val `akkaActor2.6.0` = lazy val `akkaActor2.6.0` =
ModuleID("com.typesafe.akka", "akka-actor", "2.6.0").withConfigurations(Some("compile")) cross CrossVersion.binary ModuleID("com.typesafe.akka", "akka-actor", "2.6.0").withConfigurations(
Some("compile")
) cross CrossVersion.binary
lazy val `scala2.10.4` = lazy val `scala2.10.4` =
ModuleID("org.scala-lang", "scala-library", "2.10.4").withConfigurations(Some("compile")) ModuleID("org.scala-lang", "scala-library", "2.10.4").withConfigurations(Some("compile"))
lazy val `scala2.12.17` = lazy val `scala2.12.17` =
@ -130,9 +136,13 @@ object EvictionErrorSpec extends BaseIvySpecification {
lazy val `scala2.13.3` = lazy val `scala2.13.3` =
ModuleID("org.scala-lang", "scala-library", "2.13.3").withConfigurations(Some("compile")) ModuleID("org.scala-lang", "scala-library", "2.13.3").withConfigurations(Some("compile"))
lazy val `bananaSesame0.4` = lazy val `bananaSesame0.4` =
ModuleID("org.w3", "banana-sesame", "0.4").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.1.4 ModuleID("org.w3", "banana-sesame", "0.4").withConfigurations(
Some("compile")
) cross CrossVersion.binary // uses akka-actor 2.1.4
lazy val `akkaRemote2.3.4` = lazy val `akkaRemote2.3.4` =
ModuleID("com.typesafe.akka", "akka-remote", "2.3.4").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.3.4 ModuleID("com.typesafe.akka", "akka-remote", "2.3.4").withConfigurations(
Some("compile")
) cross CrossVersion.binary // uses akka-actor 2.3.4
lazy val `http4s0.21.11` = lazy val `http4s0.21.11` =
("org.http4s" %% "http4s-blaze-server" % "0.21.11").withConfigurations(Some("compile")) ("org.http4s" %% "http4s-blaze-server" % "0.21.11").withConfigurations(Some("compile"))
// https://repo1.maven.org/maven2/org/typelevel/cats-effect_2.13/3.0.0-M4/cats-effect_2.13-3.0.0-M4.pom // https://repo1.maven.org/maven2/org/typelevel/cats-effect_2.13/3.0.0-M4/cats-effect_2.13-3.0.0-M4.pom

View File

@ -20,7 +20,11 @@ object EvictionWarningSpec extends BaseIvySpecification {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false) val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
val report = ivyUpdate(m) val report = ivyUpdate(m)
assert( assert(
EvictionWarning(m, fullOptions.withWarnScalaVersionEviction(false), report).scalaEvictions.size == 0 EvictionWarning(
m,
fullOptions.withWarnScalaVersionEviction(false),
report
).scalaEvictions.size == 0
) )
} }
@ -79,7 +83,11 @@ object EvictionWarningSpec extends BaseIvySpecification {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2")) val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"))
val report = ivyUpdate(m) val report = ivyUpdate(m)
assert( assert(
EvictionWarning(m, fullOptions.withWarnScalaVersionEviction(false), report).scalaEvictions.size == 0 EvictionWarning(
m,
fullOptions.withWarnScalaVersionEviction(false),
report
).scalaEvictions.size == 0
) )
} }
@ -302,11 +310,17 @@ object EvictionWarningSpec extends BaseIvySpecification {
} }
def akkaActor214 = def akkaActor214 =
ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(Some("compile")) cross CrossVersion.binary ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(
Some("compile")
) cross CrossVersion.binary
def akkaActor230 = def akkaActor230 =
ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("compile")) cross CrossVersion.binary ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(
Some("compile")
) cross CrossVersion.binary
def akkaActor234 = def akkaActor234 =
ModuleID("com.typesafe.akka", "akka-actor", "2.3.4").withConfigurations(Some("compile")) cross CrossVersion.binary ModuleID("com.typesafe.akka", "akka-actor", "2.3.4").withConfigurations(
Some("compile")
) cross CrossVersion.binary
def scala2102 = def scala2102 =
ModuleID("org.scala-lang", "scala-library", "2.10.2").withConfigurations(Some("compile")) ModuleID("org.scala-lang", "scala-library", "2.10.2").withConfigurations(Some("compile"))
def scala2103 = def scala2103 =
@ -317,13 +331,21 @@ object EvictionWarningSpec extends BaseIvySpecification {
def commonsIo14 = ModuleID("commons-io", "commons-io", "1.4").withConfigurations(Some("compile")) def commonsIo14 = ModuleID("commons-io", "commons-io", "1.4").withConfigurations(Some("compile"))
def commonsIo24 = ModuleID("commons-io", "commons-io", "2.4").withConfigurations(Some("compile")) def commonsIo24 = ModuleID("commons-io", "commons-io", "2.4").withConfigurations(Some("compile"))
def bnfparser10 = def bnfparser10 =
ModuleID("ca.gobits.bnf", "bnfparser", "1.0").withConfigurations(Some("compile")) // uses commons-io 2.4 ModuleID("ca.gobits.bnf", "bnfparser", "1.0").withConfigurations(
Some("compile")
) // uses commons-io 2.4
def unfilteredUploads080 = def unfilteredUploads080 =
ModuleID("net.databinder", "unfiltered-uploads", "0.8.0").withConfigurations(Some("compile")) cross CrossVersion.binary // uses commons-io 1.4 ModuleID("net.databinder", "unfiltered-uploads", "0.8.0").withConfigurations(
Some("compile")
) cross CrossVersion.binary // uses commons-io 1.4
def bananaSesame04 = def bananaSesame04 =
ModuleID("org.w3", "banana-sesame", "0.4").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.1.4 ModuleID("org.w3", "banana-sesame", "0.4").withConfigurations(
Some("compile")
) cross CrossVersion.binary // uses akka-actor 2.1.4
def akkaRemote234 = def akkaRemote234 =
ModuleID("com.typesafe.akka", "akka-remote", "2.3.4").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.3.4 ModuleID("com.typesafe.akka", "akka-remote", "2.3.4").withConfigurations(
Some("compile")
) cross CrossVersion.binary // uses akka-actor 2.3.4
def fullOptions = EvictionWarningOptions.full def fullOptions = EvictionWarningOptions.full
def javaLibDirectDeps = Vector(commonsIo14, commonsIo24) def javaLibDirectDeps = Vector(commonsIo14, commonsIo24)

View File

@ -24,9 +24,15 @@ object InconsistentDuplicateSpec extends BasicTestSuite {
} }
def akkaActor214 = def akkaActor214 =
ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(Some("compile")) cross CrossVersion.binary ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(
Some("compile")
) cross CrossVersion.binary
def akkaActor230 = def akkaActor230 =
ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("compile")) cross CrossVersion.binary ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(
Some("compile")
) cross CrossVersion.binary
def akkaActor230Test = def akkaActor230Test =
ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("test")) cross CrossVersion.binary ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(
Some("test")
) cross CrossVersion.binary
} }

View File

@ -17,7 +17,7 @@ object IvyRepoSpec extends BaseIvySpecification {
module( module(
ourModuleID, ourModuleID,
Vector(dep), Vector(dep),
None //, UpdateOptions().withCachedResolution(true) None // , UpdateOptions().withCachedResolution(true)
) )
} }
@ -31,13 +31,11 @@ object IvyRepoSpec extends BaseIvySpecification {
val report = ivyUpdate(m) val report = ivyUpdate(m)
import Inside._ import Inside._
inside(report.configuration(ConfigRef("compile")).map(_.modules)) { inside(report.configuration(ConfigRef("compile")).map(_.modules)) { case Some(Seq(mr)) =>
case Some(Seq(mr)) => inside(mr.artifacts) { case Seq((ar, _)) =>
inside(mr.artifacts) { assert(ar.`type` == "jar")
case Seq((ar, _)) => assert(ar.extension == "jar")
assert(ar.`type` == "jar") }
assert(ar.extension == "jar")
}
} }
} }
@ -90,14 +88,12 @@ object IvyRepoSpec extends BaseIvySpecification {
.get .get
import Inside._ import Inside._
inside(report2.configuration(ConfigRef("compile")).map(_.modules)) { inside(report2.configuration(ConfigRef("compile")).map(_.modules)) { case Some(Seq(mr)) =>
case Some(Seq(mr)) => inside(mr.artifacts) { case Seq((ar, _)) =>
inside(mr.artifacts) { assert(ar.name == "libmodule-source")
case Seq((ar, _)) => assert(ar.`type` == "src")
assert(ar.name == "libmodule-source") assert(ar.extension == "jar")
assert(ar.`type` == "src") }
assert(ar.extension == "jar")
}
} }
} }

View File

@ -14,20 +14,19 @@ object MergeDescriptorSpec extends BaseIvySpecification {
None, None,
UpdateOptions() UpdateOptions()
) )
m.withModule(log) { m.withModule(log) { case (_, md, _) =>
case (_, md, _) => val deps = md.getDependencies
val deps = md.getDependencies assert(deps.size == 1)
assert(deps.size == 1) deps.headOption.getOrElse(sys.error("Dependencies not found")) match {
deps.headOption.getOrElse(sys.error("Dependencies not found")) match { case dd @ MergedDescriptors(_, _) =>
case dd @ MergedDescriptors(_, _) => val arts = dd.getAllDependencyArtifacts
val arts = dd.getAllDependencyArtifacts val a0: DependencyArtifactDescriptor = arts.toList(0)
val a0: DependencyArtifactDescriptor = arts.toList(0) val a1: DependencyArtifactDescriptor = arts.toList(1)
val a1: DependencyArtifactDescriptor = arts.toList(1) val configs0 = a0.getConfigurations.toList
val configs0 = a0.getConfigurations.toList val configs1 = a1.getConfigurations.toList
val configs1 = a1.getConfigurations.toList assert(configs0 == List("compile"))
assert(configs0 == List("compile")) assert(configs1 == List("test"))
assert(configs1 == List("test")) }
}
} }
} }
def guavaTest = def guavaTest =

View File

@ -13,7 +13,7 @@ import java.nio.file.Paths
object SftpRepoSpec extends BaseIvySpecification { object SftpRepoSpec extends BaseIvySpecification {
val repo: Option[String] = None val repo: Option[String] = None
// val repo: Option[String] = Some("some repo") // val repo: Option[String] = Some("some repo")
//a dependency which depends on another in the repo // a dependency which depends on another in the repo
def org(repo: String) = s"com.${repo}" def org(repo: String) = s"com.${repo}"
def module(org: String) = org % "some-lib" % "version" def module(org: String) = org % "some-lib" % "version"

View File

@ -31,8 +31,8 @@ object HouseRulesPlugin extends AutoPlugin {
scalacOptions += "-Ywarn-numeric-widen", scalacOptions += "-Ywarn-numeric-widen",
scalacOptions += "-Ywarn-value-discard", scalacOptions += "-Ywarn-value-discard",
scalacOptions ++= "-Ywarn-unused-import".ifScala(v => 11 <= v && v <= 12).value.toList scalacOptions ++= "-Ywarn-unused-import".ifScala(v => 11 <= v && v <= 12).value.toList
) ++ Seq(Compile, Test).flatMap( ) ++ Seq(Compile, Test).flatMap(c =>
c => (c / console / scalacOptions) --= Seq("-Ywarn-unused-import", "-Xlint") (c / console / scalacOptions) --= Seq("-Ywarn-unused-import", "-Xlint")
) )
private def scalaPartV = Def setting (CrossVersion partialVersion scalaVersion.value) private def scalaPartV = Def setting (CrossVersion partialVersion scalaVersion.value)

View File

@ -30,7 +30,9 @@ object Util {
val f = dir / "xsbt.version.properties" val f = dir / "xsbt.version.properties"
// TODO: replace lastModified() with sbt.io.IO.getModifiedTimeOrZero(), once the build // TODO: replace lastModified() with sbt.io.IO.getModifiedTimeOrZero(), once the build
// has been upgraded to a version of sbt that includes that call. // has been upgraded to a version of sbt that includes that call.
if (!f.exists || f.lastModified < lastCompilationTime(analysis) || !containsVersion(f, version)) { if (
!f.exists || f.lastModified < lastCompilationTime(analysis) || !containsVersion(f, version)
) {
s.log.info("Writing version information to " + f + " :\n" + content) s.log.info("Writing version information to " + f + " :\n" + content)
IO.write(f, content) IO.write(f, content)
} }