mirror of https://github.com/sbt/sbt.git
Apply formatting
This commit is contained in:
parent
712c83f859
commit
d42ea869d0
62
build.sbt
62
build.sbt
|
|
@ -28,17 +28,19 @@ def commonSettings: Seq[Setting[_]] = Seq(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
lazy val lmRoot = (project in file(".")).
|
lazy val lmRoot = (project in file("."))
|
||||||
aggregate(lm).
|
.aggregate(lm)
|
||||||
disablePlugins(com.typesafe.sbt.SbtScalariform).
|
.disablePlugins(com.typesafe.sbt.SbtScalariform)
|
||||||
settings(
|
.settings(
|
||||||
inThisBuild(Seq(
|
inThisBuild(
|
||||||
homepage := Some(url("https://github.com/sbt/librarymanagement")),
|
Seq(
|
||||||
description := "Library management module for sbt",
|
homepage := Some(url("https://github.com/sbt/librarymanagement")),
|
||||||
scmInfo := Some(ScmInfo(url("https://github.com/sbt/librarymanagement"), "git@github.com:sbt/librarymanagement.git")),
|
description := "Library management module for sbt",
|
||||||
bintrayPackage := "librarymanagement",
|
scmInfo := Some(ScmInfo(url("https://github.com/sbt/librarymanagement"),
|
||||||
git.baseVersion := baseVersion
|
"git@github.com:sbt/librarymanagement.git")),
|
||||||
)),
|
bintrayPackage := "librarymanagement",
|
||||||
|
git.baseVersion := baseVersion
|
||||||
|
)),
|
||||||
commonSettings,
|
commonSettings,
|
||||||
name := "LM Root",
|
name := "LM Root",
|
||||||
publish := {},
|
publish := {},
|
||||||
|
|
@ -48,15 +50,24 @@ lazy val lmRoot = (project in file(".")).
|
||||||
customCommands
|
customCommands
|
||||||
)
|
)
|
||||||
|
|
||||||
lazy val lm = (project in file("librarymanagement")).
|
lazy val lm = (project in file("librarymanagement"))
|
||||||
disablePlugins(com.typesafe.sbt.SbtScalariform).
|
.disablePlugins(com.typesafe.sbt.SbtScalariform)
|
||||||
settings(
|
.settings(
|
||||||
commonSettings,
|
commonSettings,
|
||||||
name := "librarymanagement",
|
name := "librarymanagement",
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(ivy,
|
||||||
ivy, jsch, scalaReflect.value, launcherInterface, sjsonnewScalaJson % Optional),
|
jsch,
|
||||||
|
scalaReflect.value,
|
||||||
|
launcherInterface,
|
||||||
|
sjsonnewScalaJson % Optional),
|
||||||
libraryDependencies ++= scalaXml.value,
|
libraryDependencies ++= scalaXml.value,
|
||||||
resourceGenerators in Compile += Def.task(Util.generateVersionFile(version.value, resourceManaged.value, streams.value, (compile in Compile).value)).taskValue,
|
resourceGenerators in Compile += Def
|
||||||
|
.task(
|
||||||
|
Util.generateVersionFile(version.value,
|
||||||
|
resourceManaged.value,
|
||||||
|
streams.value,
|
||||||
|
(compile in Compile).value))
|
||||||
|
.taskValue,
|
||||||
mimaBinaryIssueFilters ++= Seq(),
|
mimaBinaryIssueFilters ++= Seq(),
|
||||||
contrabandFormatsForType in generateContrabands in Compile := DatatypeConfig.getFormats,
|
contrabandFormatsForType in generateContrabands in Compile := DatatypeConfig.getFormats,
|
||||||
// WORKAROUND sbt/sbt#2205 include managed sources in packageSrc
|
// WORKAROUND sbt/sbt#2205 include managed sources in packageSrc
|
||||||
|
|
@ -66,16 +77,21 @@ lazy val lm = (project in file("librarymanagement")).
|
||||||
val base = baseDirectory.value
|
val base = baseDirectory.value
|
||||||
(((srcs --- sdirs --- base) pair (relativeTo(sdirs) | relativeTo(base) | flat)) toSeq)
|
(((srcs --- sdirs --- base) pair (relativeTo(sdirs) | relativeTo(base) | flat)) toSeq)
|
||||||
}
|
}
|
||||||
).
|
)
|
||||||
configure(addSbtIO, addSbtUtilLogging, addSbtUtilTesting, addSbtUtilCollection, addSbtUtilCompletion, addSbtUtilCache).
|
.configure(addSbtIO,
|
||||||
enablePlugins(ContrabandPlugin, JsonCodecPlugin)
|
addSbtUtilLogging,
|
||||||
|
addSbtUtilTesting,
|
||||||
|
addSbtUtilCollection,
|
||||||
|
addSbtUtilCompletion,
|
||||||
|
addSbtUtilCache)
|
||||||
|
.enablePlugins(ContrabandPlugin, JsonCodecPlugin)
|
||||||
|
|
||||||
def customCommands: Seq[Setting[_]] = Seq(
|
def customCommands: Seq[Setting[_]] = Seq(
|
||||||
commands += Command.command("release") { state =>
|
commands += Command.command("release") { state =>
|
||||||
// "clean" ::
|
// "clean" ::
|
||||||
"so compile" ::
|
"so compile" ::
|
||||||
"so publishSigned" ::
|
"so publishSigned" ::
|
||||||
"reload" ::
|
"reload" ::
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -37,68 +37,83 @@ object ReplaceMavenConfigurationMappings {
|
||||||
|
|
||||||
// NOTE - This code is copied from org.apache.ivy.plugins.parser.m2.PomModuleDescriptorBuilder
|
// NOTE - This code is copied from org.apache.ivy.plugins.parser.m2.PomModuleDescriptorBuilder
|
||||||
// except with altered default configurations...
|
// except with altered default configurations...
|
||||||
REPLACEMENT_MAPPINGS.put("compile", new PomModuleDescriptorBuilder.ConfMapper {
|
REPLACEMENT_MAPPINGS.put(
|
||||||
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean): Unit = {
|
"compile",
|
||||||
if (isOptional) {
|
new PomModuleDescriptorBuilder.ConfMapper {
|
||||||
dd.addDependencyConfiguration("optional", "compile(*)")
|
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean): Unit = {
|
||||||
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
if (isOptional) {
|
||||||
dd.addDependencyConfiguration("optional", "master(compile)")
|
dd.addDependencyConfiguration("optional", "compile(*)")
|
||||||
} else {
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
dd.addDependencyConfiguration("compile", "compile(*)")
|
dd.addDependencyConfiguration("optional", "master(compile)")
|
||||||
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
} else {
|
||||||
dd.addDependencyConfiguration("compile", "master(compile)")
|
dd.addDependencyConfiguration("compile", "compile(*)")
|
||||||
dd.addDependencyConfiguration("runtime", "runtime(*)")
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("compile", "master(compile)")
|
||||||
|
dd.addDependencyConfiguration("runtime", "runtime(*)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
REPLACEMENT_MAPPINGS.put("provided", new PomModuleDescriptorBuilder.ConfMapper {
|
REPLACEMENT_MAPPINGS.put(
|
||||||
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean): Unit = {
|
"provided",
|
||||||
if (isOptional) {
|
new PomModuleDescriptorBuilder.ConfMapper {
|
||||||
dd.addDependencyConfiguration("optional", "compile(*)")
|
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean): Unit = {
|
||||||
dd.addDependencyConfiguration("optional", "provided(*)")
|
if (isOptional) {
|
||||||
dd.addDependencyConfiguration("optional", "runtime(*)")
|
dd.addDependencyConfiguration("optional", "compile(*)")
|
||||||
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
dd.addDependencyConfiguration("optional", "provided(*)")
|
||||||
dd.addDependencyConfiguration("optional", "master(compile)")
|
dd.addDependencyConfiguration("optional", "runtime(*)")
|
||||||
} else {
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
dd.addDependencyConfiguration("provided", "compile(*)")
|
dd.addDependencyConfiguration("optional", "master(compile)")
|
||||||
dd.addDependencyConfiguration("provided", "provided(*)")
|
} else {
|
||||||
dd.addDependencyConfiguration("provided", "runtime(*)")
|
dd.addDependencyConfiguration("provided", "compile(*)")
|
||||||
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
dd.addDependencyConfiguration("provided", "provided(*)")
|
||||||
dd.addDependencyConfiguration("provided", "master(compile)")
|
dd.addDependencyConfiguration("provided", "runtime(*)")
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("provided", "master(compile)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
|
|
||||||
REPLACEMENT_MAPPINGS.put("runtime", new PomModuleDescriptorBuilder.ConfMapper {
|
REPLACEMENT_MAPPINGS.put(
|
||||||
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean): Unit = {
|
"runtime",
|
||||||
if (isOptional) {
|
new PomModuleDescriptorBuilder.ConfMapper {
|
||||||
dd.addDependencyConfiguration("optional", "compile(*)")
|
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean): Unit = {
|
||||||
dd.addDependencyConfiguration("optional", "provided(*)")
|
if (isOptional) {
|
||||||
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
dd.addDependencyConfiguration("optional", "compile(*)")
|
||||||
dd.addDependencyConfiguration("optional", "master(compile)")
|
dd.addDependencyConfiguration("optional", "provided(*)")
|
||||||
} else {
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
dd.addDependencyConfiguration("runtime", "compile(*)")
|
dd.addDependencyConfiguration("optional", "master(compile)")
|
||||||
dd.addDependencyConfiguration("runtime", "runtime(*)")
|
} else {
|
||||||
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
dd.addDependencyConfiguration("runtime", "compile(*)")
|
||||||
dd.addDependencyConfiguration("runtime", "master(compile)")
|
dd.addDependencyConfiguration("runtime", "runtime(*)")
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("runtime", "master(compile)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
|
|
||||||
REPLACEMENT_MAPPINGS.put("test", new PomModuleDescriptorBuilder.ConfMapper {
|
REPLACEMENT_MAPPINGS.put(
|
||||||
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean): Unit = {
|
"test",
|
||||||
dd.addDependencyConfiguration("test", "runtime(*)")
|
new PomModuleDescriptorBuilder.ConfMapper {
|
||||||
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean): Unit = {
|
||||||
dd.addDependencyConfiguration("test", "master(compile)")
|
dd.addDependencyConfiguration("test", "runtime(*)")
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("test", "master(compile)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
|
|
||||||
REPLACEMENT_MAPPINGS.put("system", new PomModuleDescriptorBuilder.ConfMapper {
|
REPLACEMENT_MAPPINGS.put(
|
||||||
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean): Unit = {
|
"system",
|
||||||
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
new PomModuleDescriptorBuilder.ConfMapper {
|
||||||
dd.addDependencyConfiguration("system", "master(compile)")
|
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean): Unit = {
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("system", "master(compile)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
|
|
||||||
REPLACEMENT_MAPPINGS
|
REPLACEMENT_MAPPINGS
|
||||||
}
|
}
|
||||||
|
|
@ -106,13 +121,17 @@ object ReplaceMavenConfigurationMappings {
|
||||||
def init(): Unit = {
|
def init(): Unit = {
|
||||||
// Here we mutate a static final field, because we have to AND because it's evil.
|
// Here we mutate a static final field, because we have to AND because it's evil.
|
||||||
try {
|
try {
|
||||||
val map = PomModuleDescriptorBuilder.MAVEN2_CONF_MAPPING.asInstanceOf[java.util.Map[String, PomModuleDescriptorBuilder.ConfMapper]]
|
val map = PomModuleDescriptorBuilder.MAVEN2_CONF_MAPPING
|
||||||
|
.asInstanceOf[java.util.Map[String, PomModuleDescriptorBuilder.ConfMapper]]
|
||||||
map.clear()
|
map.clear()
|
||||||
map.putAll(REPLACEMENT_MAVEN_MAPPINGS)
|
map.putAll(REPLACEMENT_MAVEN_MAPPINGS)
|
||||||
} catch {
|
} catch {
|
||||||
case e: Exception =>
|
case e: Exception =>
|
||||||
// TODO - Log that Ivy may not be configured correctly and you could have maven/ivy issues.
|
// TODO - Log that Ivy may not be configured correctly and you could have maven/ivy issues.
|
||||||
throw new RuntimeException("FAILURE to install Ivy maven hooks. Your ivy-maven interaction may suffer resolution errors", e)
|
throw new RuntimeException(
|
||||||
|
"FAILURE to install Ivy maven hooks. Your ivy-maven interaction may suffer resolution errors",
|
||||||
|
e
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,16 @@ import sbt.util.{ Level, Logger }
|
||||||
import Configurations._
|
import Configurations._
|
||||||
|
|
||||||
final class CompatibilityWarningOptions private[sbt] (
|
final class CompatibilityWarningOptions private[sbt] (
|
||||||
val configurations: Seq[Configuration],
|
val configurations: Seq[Configuration],
|
||||||
val level: Level.Value
|
val level: Level.Value
|
||||||
)
|
)
|
||||||
|
|
||||||
object CompatibilityWarningOptions {
|
object CompatibilityWarningOptions {
|
||||||
def default: CompatibilityWarningOptions =
|
def default: CompatibilityWarningOptions =
|
||||||
apply(configurations = List(Compile, Runtime), level = Level.Warn)
|
apply(configurations = List(Compile, Runtime), level = Level.Warn)
|
||||||
def apply(
|
def apply(
|
||||||
configurations: List[Configuration],
|
configurations: List[Configuration],
|
||||||
level: Level.Value
|
level: Level.Value
|
||||||
): CompatibilityWarningOptions =
|
): CompatibilityWarningOptions =
|
||||||
new CompatibilityWarningOptions(
|
new CompatibilityWarningOptions(
|
||||||
configurations = configurations,
|
configurations = configurations,
|
||||||
|
|
@ -24,12 +24,21 @@ object CompatibilityWarningOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] object CompatibilityWarning {
|
private[sbt] object CompatibilityWarning {
|
||||||
def run(config: CompatibilityWarningOptions, module: IvySbt#Module, mavenStyle: Boolean, log: Logger): Unit = {
|
def run(
|
||||||
|
config: CompatibilityWarningOptions,
|
||||||
|
module: IvySbt#Module,
|
||||||
|
mavenStyle: Boolean,
|
||||||
|
log: Logger
|
||||||
|
): Unit = {
|
||||||
if (mavenStyle) {
|
if (mavenStyle) {
|
||||||
processIntransitive(config, module, log)
|
processIntransitive(config, module, log)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def processIntransitive(config: CompatibilityWarningOptions, module: IvySbt#Module, log: Logger): Unit = {
|
def processIntransitive(
|
||||||
|
config: CompatibilityWarningOptions,
|
||||||
|
module: IvySbt#Module,
|
||||||
|
log: Logger
|
||||||
|
): Unit = {
|
||||||
val monitoredConfigsStr: Set[String] = (config.configurations map { _.name }).toSet
|
val monitoredConfigsStr: Set[String] = (config.configurations map { _.name }).toSet
|
||||||
val directDependencies: Seq[ModuleID] = module.moduleSettings match {
|
val directDependencies: Seq[ModuleID] = module.moduleSettings match {
|
||||||
case x: InlineConfiguration => x.dependencies
|
case x: InlineConfiguration => x.dependencies
|
||||||
|
|
|
||||||
|
|
@ -18,54 +18,73 @@ import sbt.librarymanagement._
|
||||||
* This is used for compiled source jars so that the compilation need not be repeated for other projects on the same
|
* This is used for compiled source jars so that the compilation need not be repeated for other projects on the same
|
||||||
* machine.
|
* machine.
|
||||||
*/
|
*/
|
||||||
class ComponentManager(globalLock: xsbti.GlobalLock, provider: xsbti.ComponentProvider, ivyHome: Option[File], val log: Logger) {
|
class ComponentManager(
|
||||||
|
globalLock: xsbti.GlobalLock,
|
||||||
|
provider: xsbti.ComponentProvider,
|
||||||
|
ivyHome: Option[File],
|
||||||
|
val log: Logger
|
||||||
|
) {
|
||||||
private[this] val ivyCache = new IvyCache(ivyHome)
|
private[this] val ivyCache = new IvyCache(ivyHome)
|
||||||
/** Get all of the files for component 'id', throwing an exception if no files exist for the component. */
|
|
||||||
def files(id: String)(ifMissing: IfMissing): Iterable[File] =
|
|
||||||
{
|
|
||||||
def fromGlobal =
|
|
||||||
lockGlobalCache {
|
|
||||||
try { update(id); getOrElse(createAndCache) }
|
|
||||||
catch { case e: NotInCache => createAndCache }
|
|
||||||
}
|
|
||||||
def getOrElse(orElse: => Iterable[File]): Iterable[File] =
|
|
||||||
{
|
|
||||||
val existing = provider.component(id)
|
|
||||||
if (existing.isEmpty) orElse else existing
|
|
||||||
}
|
|
||||||
def notFound = invalid("Could not find required component '" + id + "'")
|
|
||||||
def createAndCache =
|
|
||||||
ifMissing match {
|
|
||||||
case IfMissing.Fail => notFound
|
|
||||||
case d: IfMissing.Define =>
|
|
||||||
d()
|
|
||||||
if (d.cache) cache(id)
|
|
||||||
getOrElse(notFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
lockLocalCache { getOrElse(fromGlobal) }
|
/** Get all of the files for component 'id', throwing an exception if no files exist for the component. */
|
||||||
|
def files(id: String)(ifMissing: IfMissing): Iterable[File] = {
|
||||||
|
def fromGlobal =
|
||||||
|
lockGlobalCache {
|
||||||
|
try { update(id); getOrElse(createAndCache) } catch {
|
||||||
|
case e: NotInCache => createAndCache
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def getOrElse(orElse: => Iterable[File]): Iterable[File] = {
|
||||||
|
val existing = provider.component(id)
|
||||||
|
if (existing.isEmpty) orElse else existing
|
||||||
}
|
}
|
||||||
|
def notFound = invalid("Could not find required component '" + id + "'")
|
||||||
|
def createAndCache =
|
||||||
|
ifMissing match {
|
||||||
|
case IfMissing.Fail => notFound
|
||||||
|
case d: IfMissing.Define =>
|
||||||
|
d()
|
||||||
|
if (d.cache) cache(id)
|
||||||
|
getOrElse(notFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
lockLocalCache { getOrElse(fromGlobal) }
|
||||||
|
}
|
||||||
|
|
||||||
/** 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 = globalLock(file, new Callable[T] { def call = action })
|
private def lock[T](file: File)(action: => T): T =
|
||||||
|
globalLock(file, new Callable[T] { def call = action })
|
||||||
|
|
||||||
/** Get the file for component 'id', throwing an exception if no files or multiple files exist for the component. */
|
/** Get the file for component 'id', throwing an exception if no files or multiple files exist for the component. */
|
||||||
def file(id: String)(ifMissing: IfMissing): File =
|
def file(id: String)(ifMissing: IfMissing): File =
|
||||||
files(id)(ifMissing).toList match {
|
files(id)(ifMissing).toList match {
|
||||||
case x :: Nil => x
|
case x :: Nil => x
|
||||||
case xs => invalid("Expected single file for component '" + id + "', found: " + xs.mkString(", "))
|
case xs =>
|
||||||
|
invalid("Expected single file for component '" + id + "', found: " + xs.mkString(", "))
|
||||||
}
|
}
|
||||||
private def invalid(msg: String) = throw new InvalidComponent(msg)
|
private def invalid(msg: String) = throw new InvalidComponent(msg)
|
||||||
|
|
||||||
def define(id: String, files: Iterable[File]) = lockLocalCache { provider.defineComponent(id, files.toSeq.toArray) }
|
def define(id: String, files: Iterable[File]) = lockLocalCache {
|
||||||
/** Retrieve the file for component 'id' from the local repository. */
|
provider.defineComponent(id, files.toSeq.toArray)
|
||||||
private def update(id: String): Unit = ivyCache.withCachedJar(sbtModuleID(id), Some(globalLock), log)(jar => define(id, Seq(jar)))
|
}
|
||||||
|
|
||||||
|
/** Retrieve the file for component 'id' from the local repository. */
|
||||||
|
private def update(id: String): Unit =
|
||||||
|
ivyCache.withCachedJar(sbtModuleID(id), Some(globalLock), log)(jar => define(id, Seq(jar)))
|
||||||
|
|
||||||
|
private def sbtModuleID(id: String) =
|
||||||
|
ModuleID(SbtArtifacts.Organization, id, ComponentManager.stampedVersion)
|
||||||
|
|
||||||
private def sbtModuleID(id: String) = ModuleID(SbtArtifacts.Organization, id, ComponentManager.stampedVersion)
|
|
||||||
/** Install the files for component 'id' to the local repository. This is usually used after writing files to the directory returned by 'location'. */
|
/** Install the files for component 'id' to the local repository. This is usually used after writing files to the directory returned by 'location'. */
|
||||||
def cache(id: String): Unit = ivyCache.cacheJar(sbtModuleID(id), file(id)(IfMissing.Fail), Some(globalLock), log)
|
def cache(id: String): Unit =
|
||||||
def clearCache(id: String): Unit = lockGlobalCache { ivyCache.clearCachedJar(sbtModuleID(id), Some(globalLock), log) }
|
ivyCache.cacheJar(sbtModuleID(id), file(id)(IfMissing.Fail), Some(globalLock), log)
|
||||||
|
def clearCache(id: String): Unit = lockGlobalCache {
|
||||||
|
ivyCache.clearCachedJar(sbtModuleID(id), Some(globalLock), log)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class InvalidComponent(msg: String, cause: Throwable) extends RuntimeException(msg, cause) {
|
class InvalidComponent(msg: String, cause: Throwable) extends RuntimeException(msg, cause) {
|
||||||
def this(msg: String) = this(msg, null)
|
def this(msg: String) = this(msg, null)
|
||||||
|
|
@ -73,16 +92,17 @@ class InvalidComponent(msg: String, cause: Throwable) extends RuntimeException(m
|
||||||
sealed trait IfMissing
|
sealed trait IfMissing
|
||||||
object IfMissing {
|
object IfMissing {
|
||||||
object Fail extends IfMissing
|
object Fail extends IfMissing
|
||||||
final class Define(val cache: Boolean, define: => Unit) extends IfMissing { def apply() = define }
|
final class Define(val cache: Boolean, define: => Unit) extends IfMissing {
|
||||||
|
def apply() = define
|
||||||
|
}
|
||||||
}
|
}
|
||||||
object ComponentManager {
|
object ComponentManager {
|
||||||
lazy val (version, timestamp) =
|
lazy val (version, timestamp) = {
|
||||||
{
|
val properties = new java.util.Properties
|
||||||
val properties = new java.util.Properties
|
val propertiesStream = versionResource.openStream
|
||||||
val propertiesStream = versionResource.openStream
|
try { properties.load(propertiesStream) } finally { propertiesStream.close() }
|
||||||
try { properties.load(propertiesStream) } finally { propertiesStream.close() }
|
(properties.getProperty("version"), properties.getProperty("timestamp"))
|
||||||
(properties.getProperty("version"), properties.getProperty("timestamp"))
|
}
|
||||||
}
|
|
||||||
lazy val stampedVersion = version + "_" + timestamp
|
lazy val stampedVersion = version + "_" + timestamp
|
||||||
|
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,20 @@ import org.apache.ivy.core.module.descriptor.DependencyDescriptor
|
||||||
import org.apache.ivy.core.resolve.ResolveData
|
import org.apache.ivy.core.resolve.ResolveData
|
||||||
import org.apache.ivy.core.settings.IvySettings
|
import org.apache.ivy.core.settings.IvySettings
|
||||||
import org.apache.ivy.plugins.repository.{ RepositoryCopyProgressListener, TransferEvent }
|
import org.apache.ivy.plugins.repository.{ RepositoryCopyProgressListener, TransferEvent }
|
||||||
import org.apache.ivy.plugins.resolver.{ BasicResolver, DependencyResolver, IBiblioResolver, RepositoryResolver }
|
import org.apache.ivy.plugins.resolver.{
|
||||||
import org.apache.ivy.plugins.resolver.{ AbstractPatternsBasedResolver, AbstractSshBasedResolver, FileSystemResolver, SFTPResolver, SshResolver, URLResolver }
|
BasicResolver,
|
||||||
|
DependencyResolver,
|
||||||
|
IBiblioResolver,
|
||||||
|
RepositoryResolver
|
||||||
|
}
|
||||||
|
import org.apache.ivy.plugins.resolver.{
|
||||||
|
AbstractPatternsBasedResolver,
|
||||||
|
AbstractSshBasedResolver,
|
||||||
|
FileSystemResolver,
|
||||||
|
SFTPResolver,
|
||||||
|
SshResolver,
|
||||||
|
URLResolver
|
||||||
|
}
|
||||||
import org.apache.ivy.plugins.repository.url.{ URLRepository => URLRepo }
|
import org.apache.ivy.plugins.repository.url.{ URLRepository => URLRepo }
|
||||||
import org.apache.ivy.plugins.repository.file.{ FileRepository => FileRepo, FileResource }
|
import org.apache.ivy.plugins.repository.file.{ FileRepository => FileRepo, FileResource }
|
||||||
import java.io.{ IOException, File }
|
import java.io.{ IOException, File }
|
||||||
|
|
@ -41,25 +53,35 @@ private[sbt] object ConvertResolver {
|
||||||
thing.setAccessible(true)
|
thing.setAccessible(true)
|
||||||
Some(thing)
|
Some(thing)
|
||||||
} catch {
|
} catch {
|
||||||
case (_: java.lang.NoSuchFieldException) |
|
case (_: java.lang.NoSuchFieldException) | (_: java.lang.SecurityException) |
|
||||||
(_: java.lang.SecurityException) |
|
(_: java.lang.NoSuchMethodException) =>
|
||||||
(_: java.lang.NoSuchMethodException) => None
|
None
|
||||||
}
|
}
|
||||||
private val signerNameField: Option[java.lang.reflect.Field] =
|
private val signerNameField: Option[java.lang.reflect.Field] =
|
||||||
reflectiveLookup(_.getDeclaredField("signerName"))
|
reflectiveLookup(_.getDeclaredField("signerName"))
|
||||||
private val putChecksumMethod: Option[java.lang.reflect.Method] =
|
private val putChecksumMethod: Option[java.lang.reflect.Method] =
|
||||||
reflectiveLookup(_.getDeclaredMethod(
|
reflectiveLookup(
|
||||||
"putChecksum",
|
_.getDeclaredMethod(
|
||||||
classOf[IArtifact], classOf[File], classOf[String],
|
"putChecksum",
|
||||||
classOf[Boolean], classOf[String]
|
classOf[IArtifact],
|
||||||
))
|
classOf[File],
|
||||||
|
classOf[String],
|
||||||
|
classOf[Boolean],
|
||||||
|
classOf[String]
|
||||||
|
)
|
||||||
|
)
|
||||||
private val putSignatureMethod: Option[java.lang.reflect.Method] =
|
private val putSignatureMethod: Option[java.lang.reflect.Method] =
|
||||||
reflectiveLookup(_.getDeclaredMethod(
|
reflectiveLookup(
|
||||||
"putSignature",
|
_.getDeclaredMethod(
|
||||||
classOf[IArtifact], classOf[File], classOf[String],
|
"putSignature",
|
||||||
classOf[Boolean]
|
classOf[IArtifact],
|
||||||
))
|
classOf[File],
|
||||||
|
classOf[String],
|
||||||
|
classOf[Boolean]
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default behavior of ivy's overwrite flags ignores the fact that a lot of repositories
|
* The default behavior of ivy's overwrite flags ignores the fact that a lot of repositories
|
||||||
* will autogenerate checksums *for* an artifact if it doesn't already exist. Therefore
|
* will autogenerate checksums *for* an artifact if it doesn't already exist. Therefore
|
||||||
|
|
@ -76,7 +98,12 @@ private[sbt] object ConvertResolver {
|
||||||
case Some(field) => field.get(this).asInstanceOf[String]
|
case Some(field) => field.get(this).asInstanceOf[String]
|
||||||
case None => null
|
case None => null
|
||||||
}
|
}
|
||||||
override protected def put(artifact: IArtifact, src: File, dest: String, overwrite: Boolean): Unit = {
|
override protected def put(
|
||||||
|
artifact: IArtifact,
|
||||||
|
src: File,
|
||||||
|
dest: String,
|
||||||
|
overwrite: Boolean
|
||||||
|
): Unit = {
|
||||||
// verify the checksum algorithms before uploading artifacts!
|
// verify the checksum algorithms before uploading artifacts!
|
||||||
val checksums = getChecksumAlgorithms()
|
val checksums = getChecksumAlgorithms()
|
||||||
val repository = getRepository()
|
val repository = getRepository()
|
||||||
|
|
@ -89,8 +116,9 @@ private[sbt] object ConvertResolver {
|
||||||
// we need to overwrite what it has.
|
// we need to overwrite what it has.
|
||||||
for (checksum <- checksums) {
|
for (checksum <- checksums) {
|
||||||
putChecksumMethod match {
|
putChecksumMethod match {
|
||||||
case Some(method) => method.invoke(this, artifact, src, dest, true: java.lang.Boolean, checksum)
|
case Some(method) =>
|
||||||
case None => // TODO - issue warning?
|
method.invoke(this, artifact, src, dest, true: java.lang.Boolean, checksum)
|
||||||
|
case None => // TODO - issue warning?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (signerName != null) {
|
if (signerName != null) {
|
||||||
|
|
@ -108,77 +136,84 @@ private[sbt] object ConvertResolver {
|
||||||
apply(r, settings, UpdateOptions(), log)
|
apply(r, settings, UpdateOptions(), log)
|
||||||
|
|
||||||
/** Converts the given sbt resolver into an Ivy resolver. */
|
/** Converts the given sbt resolver into an Ivy resolver. */
|
||||||
def apply(r: Resolver, settings: IvySettings, updateOptions: UpdateOptions, log: Logger): DependencyResolver =
|
def apply(
|
||||||
|
r: Resolver,
|
||||||
|
settings: IvySettings,
|
||||||
|
updateOptions: UpdateOptions,
|
||||||
|
log: Logger
|
||||||
|
): DependencyResolver =
|
||||||
(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) =>
|
||||||
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 extends IBiblioResolver with ChecksumFriendlyURLResolver with DescriptorRequired {
|
)
|
||||||
def setPatterns(): Unit = {
|
final class PluginCapableResolver
|
||||||
// done this way for access to protected methods.
|
extends IBiblioResolver
|
||||||
setArtifactPatterns(pattern)
|
with ChecksumFriendlyURLResolver
|
||||||
setIvyPatterns(pattern)
|
with DescriptorRequired {
|
||||||
}
|
def setPatterns(): Unit = {
|
||||||
|
// done this way for access to protected methods.
|
||||||
|
setArtifactPatterns(pattern)
|
||||||
|
setIvyPatterns(pattern)
|
||||||
}
|
}
|
||||||
val resolver = new PluginCapableResolver
|
|
||||||
if (repo.localIfFile) resolver.setRepository(new LocalIfFileRepo)
|
|
||||||
initializeMavenStyle(resolver, repo.name, repo.root)
|
|
||||||
resolver.setPatterns() // has to be done after initializeMavenStyle, which calls methods that overwrite the patterns
|
|
||||||
resolver
|
|
||||||
}
|
}
|
||||||
case repo: SshRepository =>
|
val resolver = new PluginCapableResolver
|
||||||
{
|
if (repo.localIfFile) resolver.setRepository(new LocalIfFileRepo)
|
||||||
val resolver = new SshResolver with DescriptorRequired
|
initializeMavenStyle(resolver, repo.name, repo.root)
|
||||||
initializeSSHResolver(resolver, repo, settings)
|
resolver
|
||||||
repo.publishPermissions.foreach(perm => resolver.setPublishPermissions(perm))
|
.setPatterns() // has to be done after initializeMavenStyle, which calls methods that overwrite the patterns
|
||||||
resolver
|
resolver
|
||||||
|
}
|
||||||
|
case repo: SshRepository => {
|
||||||
|
val resolver = new SshResolver with DescriptorRequired
|
||||||
|
initializeSSHResolver(resolver, repo, settings)
|
||||||
|
repo.publishPermissions.foreach(perm => resolver.setPublishPermissions(perm))
|
||||||
|
resolver
|
||||||
|
}
|
||||||
|
case repo: SftpRepository => {
|
||||||
|
val resolver = new SFTPResolver
|
||||||
|
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())
|
||||||
}
|
}
|
||||||
case repo: SftpRepository =>
|
resolver.setName(repo.name)
|
||||||
{
|
initializePatterns(resolver, repo.patterns, settings)
|
||||||
val resolver = new SFTPResolver
|
import repo.configuration.{ isLocal, isTransactional }
|
||||||
initializeSSHResolver(resolver, repo, settings)
|
resolver.setLocal(isLocal)
|
||||||
resolver
|
isTransactional.foreach(value => resolver.setTransactional(value.toString))
|
||||||
}
|
resolver
|
||||||
case repo: FileRepository =>
|
}
|
||||||
{
|
case repo: URLRepository => {
|
||||||
val resolver = new FileSystemResolver with DescriptorRequired {
|
val resolver = new URLResolver with ChecksumFriendlyURLResolver with DescriptorRequired
|
||||||
// Workaround for #1156
|
resolver.setName(repo.name)
|
||||||
// Temporarily in sbt 0.13.x we deprecate overwriting
|
initializePatterns(resolver, repo.patterns, settings)
|
||||||
// in local files for non-changing revisions.
|
resolver
|
||||||
// This will be fully enforced in sbt 1.0.
|
}
|
||||||
setRepository(new WarnOnOverwriteFileRepo())
|
case repo: ChainedResolver =>
|
||||||
}
|
IvySbt.resolverChain(repo.name, repo.resolvers, false, settings, log)
|
||||||
resolver.setName(repo.name)
|
case repo: RawRepository => repo.resolver
|
||||||
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
|
|
||||||
resolver.setName(repo.name)
|
|
||||||
initializePatterns(resolver, repo.patterns, settings)
|
|
||||||
resolver
|
|
||||||
}
|
|
||||||
case repo: ChainedResolver => IvySbt.resolverChain(repo.name, repo.resolvers, false, settings, log)
|
|
||||||
case repo: RawRepository => repo.resolver
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed trait DescriptorRequired extends BasicResolver {
|
private sealed trait DescriptorRequired extends BasicResolver {
|
||||||
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)))
|
try super.getDependency(dd, data)
|
||||||
try super.getDependency(dd, data) finally setDescriptor(prev)
|
finally setDescriptor(prev)
|
||||||
}
|
}
|
||||||
def descriptorString(optional: Boolean) =
|
def descriptorString(optional: Boolean) =
|
||||||
if (optional) BasicResolver.DESCRIPTOR_OPTIONAL else BasicResolver.DESCRIPTOR_REQUIRED
|
if (optional) BasicResolver.DESCRIPTOR_OPTIONAL else BasicResolver.DESCRIPTOR_REQUIRED
|
||||||
def hasExplicitURL(dd: DependencyDescriptor): Boolean =
|
def hasExplicitURL(dd: DependencyDescriptor): Boolean =
|
||||||
|
|
@ -189,35 +224,49 @@ private[sbt] object ConvertResolver {
|
||||||
resolver.setM2compatible(true)
|
resolver.setM2compatible(true)
|
||||||
resolver.setRoot(root)
|
resolver.setRoot(root)
|
||||||
}
|
}
|
||||||
private def initializeSSHResolver(resolver: AbstractSshBasedResolver, repo: SshBasedRepository, settings: IvySettings): Unit = {
|
private def initializeSSHResolver(
|
||||||
|
resolver: AbstractSshBasedResolver,
|
||||||
|
repo: SshBasedRepository,
|
||||||
|
settings: IvySettings
|
||||||
|
): Unit = {
|
||||||
resolver.setName(repo.name)
|
resolver.setName(repo.name)
|
||||||
resolver.setPassfile(null)
|
resolver.setPassfile(null)
|
||||||
initializePatterns(resolver, repo.patterns, settings)
|
initializePatterns(resolver, repo.patterns, settings)
|
||||||
initializeConnection(resolver, repo.connection)
|
initializeConnection(resolver, repo.connection)
|
||||||
}
|
}
|
||||||
private def initializeConnection(resolver: AbstractSshBasedResolver, connection: SshConnection): Unit = {
|
private def initializeConnection(
|
||||||
|
resolver: AbstractSshBasedResolver,
|
||||||
|
connection: SshConnection
|
||||||
|
): Unit = {
|
||||||
import resolver._
|
import resolver._
|
||||||
import connection._
|
import connection._
|
||||||
hostname.foreach(setHost)
|
hostname.foreach(setHost)
|
||||||
port.foreach(setPort)
|
port.foreach(setPort)
|
||||||
authentication foreach
|
authentication foreach {
|
||||||
{
|
case pa: PasswordAuthentication =>
|
||||||
case pa: PasswordAuthentication =>
|
setUser(pa.user)
|
||||||
setUser(pa.user)
|
pa.password.foreach(setUserPassword)
|
||||||
pa.password.foreach(setUserPassword)
|
case kfa: KeyFileAuthentication =>
|
||||||
case kfa: KeyFileAuthentication =>
|
setKeyFile(kfa.keyfile)
|
||||||
setKeyFile(kfa.keyfile)
|
kfa.password.foreach(setKeyFilePassword)
|
||||||
kfa.password.foreach(setKeyFilePassword)
|
setUser(kfa.user)
|
||||||
setUser(kfa.user)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
private def initializePatterns(resolver: AbstractPatternsBasedResolver, patterns: Patterns, settings: IvySettings): Unit = {
|
private def initializePatterns(
|
||||||
|
resolver: AbstractPatternsBasedResolver,
|
||||||
|
patterns: Patterns,
|
||||||
|
settings: IvySettings
|
||||||
|
): Unit = {
|
||||||
resolver.setM2compatible(patterns.isMavenCompatible)
|
resolver.setM2compatible(patterns.isMavenCompatible)
|
||||||
resolver.setDescriptor(if (patterns.descriptorOptional) BasicResolver.DESCRIPTOR_OPTIONAL else BasicResolver.DESCRIPTOR_REQUIRED)
|
resolver.setDescriptor(
|
||||||
|
if (patterns.descriptorOptional) BasicResolver.DESCRIPTOR_OPTIONAL
|
||||||
|
else BasicResolver.DESCRIPTOR_REQUIRED
|
||||||
|
)
|
||||||
resolver.setCheckconsistency(!patterns.skipConsistencyCheck)
|
resolver.setCheckconsistency(!patterns.skipConsistencyCheck)
|
||||||
patterns.ivyPatterns.foreach(p => resolver.addIvyPattern(settings substitute p))
|
patterns.ivyPatterns.foreach(p => resolver.addIvyPattern(settings substitute p))
|
||||||
patterns.artifactPatterns.foreach(p => resolver.addArtifactPattern(settings substitute p))
|
patterns.artifactPatterns.foreach(p => resolver.addArtifactPattern(settings substitute p))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A custom Ivy URLRepository that returns FileResources for file URLs.
|
* A custom Ivy URLRepository that returns FileResources for file URLs.
|
||||||
* This allows using the artifacts from the Maven local repository instead of copying them to the Ivy cache.
|
* This allows using the artifacts from the Maven local repository instead of copying them to the Ivy cache.
|
||||||
|
|
@ -270,7 +319,9 @@ private[sbt] object ConvertResolver {
|
||||||
catch {
|
catch {
|
||||||
case e: java.io.IOException if e.getMessage.contains("destination already exists") =>
|
case e: java.io.IOException if e.getMessage.contains("destination already exists") =>
|
||||||
import org.apache.ivy.util.Message
|
import org.apache.ivy.util.Message
|
||||||
Message.warn(s"Attempting to overwrite $destination\n\tThis usage is deprecated and will be removed in sbt 1.0.")
|
Message.warn(
|
||||||
|
s"Attempting to overwrite $destination\n\tThis usage is deprecated and will be removed in sbt 1.0."
|
||||||
|
)
|
||||||
super.put(source, destination, true)
|
super.put(source, destination, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,62 @@
|
||||||
package sbt.internal.librarymanagement
|
package sbt.internal.librarymanagement
|
||||||
|
|
||||||
import org.apache.ivy.core.module.id.ModuleRevisionId
|
import org.apache.ivy.core.module.id.ModuleRevisionId
|
||||||
import org.apache.ivy.core.module.descriptor.{ DefaultArtifact, DefaultExtendsDescriptor, DefaultModuleDescriptor, ModuleDescriptor }
|
import org.apache.ivy.core.module.descriptor.{
|
||||||
|
DefaultArtifact,
|
||||||
|
DefaultExtendsDescriptor,
|
||||||
|
DefaultModuleDescriptor,
|
||||||
|
ModuleDescriptor
|
||||||
|
}
|
||||||
import org.apache.ivy.core.module.descriptor.{ DefaultDependencyDescriptor, DependencyDescriptor }
|
import org.apache.ivy.core.module.descriptor.{ DefaultDependencyDescriptor, DependencyDescriptor }
|
||||||
import org.apache.ivy.plugins.parser.{ ModuleDescriptorParser, ModuleDescriptorParserRegistry, ParserSettings }
|
import org.apache.ivy.plugins.parser.{
|
||||||
import org.apache.ivy.plugins.parser.m2.{ ReplaceMavenConfigurationMappings, PomModuleDescriptorBuilder, PomModuleDescriptorParser }
|
ModuleDescriptorParser,
|
||||||
|
ModuleDescriptorParserRegistry,
|
||||||
|
ParserSettings
|
||||||
|
}
|
||||||
|
import org.apache.ivy.plugins.parser.m2.{
|
||||||
|
ReplaceMavenConfigurationMappings,
|
||||||
|
PomModuleDescriptorBuilder,
|
||||||
|
PomModuleDescriptorParser
|
||||||
|
}
|
||||||
import org.apache.ivy.plugins.repository.Resource
|
import org.apache.ivy.plugins.repository.Resource
|
||||||
import org.apache.ivy.plugins.namespace.NamespaceTransformer
|
import org.apache.ivy.plugins.namespace.NamespaceTransformer
|
||||||
import org.apache.ivy.util.extendable.ExtendableItem
|
import org.apache.ivy.util.extendable.ExtendableItem
|
||||||
|
|
||||||
import java.io.{ File, InputStream }
|
import java.io.{ File, InputStream }
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import sbt.internal.librarymanagement.mavenint.{ PomExtraDependencyAttributes, SbtPomExtraProperties }
|
import sbt.internal.librarymanagement.mavenint.{
|
||||||
|
PomExtraDependencyAttributes,
|
||||||
|
SbtPomExtraProperties
|
||||||
|
}
|
||||||
import sbt.io.Hash
|
import sbt.io.Hash
|
||||||
|
|
||||||
// @deprecated("We now use an Aether-based pom parser.", "0.13.8")
|
// @deprecated("We now use an Aether-based pom parser.", "0.13.8")
|
||||||
final class CustomPomParser(delegate: ModuleDescriptorParser, transform: (ModuleDescriptorParser, ModuleDescriptor) => ModuleDescriptor) extends ModuleDescriptorParser {
|
final class CustomPomParser(
|
||||||
override def parseDescriptor(ivySettings: ParserSettings, descriptorURL: URL, validate: Boolean) =
|
delegate: ModuleDescriptorParser,
|
||||||
|
transform: (ModuleDescriptorParser, ModuleDescriptor) => ModuleDescriptor
|
||||||
|
) extends ModuleDescriptorParser {
|
||||||
|
override def parseDescriptor(
|
||||||
|
ivySettings: ParserSettings,
|
||||||
|
descriptorURL: URL,
|
||||||
|
validate: Boolean
|
||||||
|
) =
|
||||||
transform(this, delegate.parseDescriptor(ivySettings, descriptorURL, validate))
|
transform(this, delegate.parseDescriptor(ivySettings, descriptorURL, validate))
|
||||||
|
|
||||||
override def parseDescriptor(ivySettings: ParserSettings, descriptorURL: URL, res: Resource, validate: Boolean) =
|
override def parseDescriptor(
|
||||||
|
ivySettings: ParserSettings,
|
||||||
|
descriptorURL: URL,
|
||||||
|
res: Resource,
|
||||||
|
validate: Boolean
|
||||||
|
) =
|
||||||
transform(this, delegate.parseDescriptor(ivySettings, descriptorURL, res, validate))
|
transform(this, delegate.parseDescriptor(ivySettings, descriptorURL, res, validate))
|
||||||
|
|
||||||
override def toIvyFile(is: InputStream, res: Resource, destFile: File, md: ModuleDescriptor) = delegate.toIvyFile(is, res, destFile, md)
|
override def toIvyFile(is: InputStream, res: Resource, destFile: File, md: ModuleDescriptor) =
|
||||||
|
delegate.toIvyFile(is, res, destFile, md)
|
||||||
|
|
||||||
override def accept(res: Resource) = delegate.accept(res)
|
override def accept(res: Resource) = delegate.accept(res)
|
||||||
override def getType() = delegate.getType()
|
override def getType() = delegate.getType()
|
||||||
override def getMetadataArtifact(mrid: ModuleRevisionId, res: Resource) = delegate.getMetadataArtifact(mrid, res)
|
override def getMetadataArtifact(mrid: ModuleRevisionId, res: Resource) =
|
||||||
|
delegate.getMetadataArtifact(mrid, res)
|
||||||
}
|
}
|
||||||
// @deprecated("We now use an Aether-based pom parser.", "0.13.8")
|
// @deprecated("We now use an Aether-based pom parser.", "0.13.8")
|
||||||
object CustomPomParser {
|
object CustomPomParser {
|
||||||
|
|
@ -41,7 +71,8 @@ object CustomPomParser {
|
||||||
val SbtVersionKey = PomExtraDependencyAttributes.SbtVersionKey
|
val SbtVersionKey = PomExtraDependencyAttributes.SbtVersionKey
|
||||||
val ScalaVersionKey = PomExtraDependencyAttributes.ScalaVersionKey
|
val ScalaVersionKey = PomExtraDependencyAttributes.ScalaVersionKey
|
||||||
val ExtraAttributesKey = PomExtraDependencyAttributes.ExtraAttributesKey
|
val ExtraAttributesKey = PomExtraDependencyAttributes.ExtraAttributesKey
|
||||||
private[this] val unqualifiedKeys = Set(SbtVersionKey, ScalaVersionKey, ExtraAttributesKey, ApiURLKey)
|
private[this] val unqualifiedKeys =
|
||||||
|
Set(SbtVersionKey, ScalaVersionKey, ExtraAttributesKey, ApiURLKey)
|
||||||
|
|
||||||
// packagings that should be jars, but that Ivy doesn't handle as jars
|
// packagings that should be jars, but that Ivy doesn't handle as jars
|
||||||
// TODO - move this elsewhere.
|
// TODO - move this elsewhere.
|
||||||
|
|
@ -51,7 +82,8 @@ object CustomPomParser {
|
||||||
private[this] val TransformedHashKey = "e:sbtTransformHash"
|
private[this] val TransformedHashKey = "e:sbtTransformHash"
|
||||||
// A hash of the parameters transformation is based on.
|
// A hash of the parameters transformation is based on.
|
||||||
// If a descriptor has a different hash, we need to retransform it.
|
// If a descriptor has a different hash, we need to retransform it.
|
||||||
private[this] def makeCoords(mrid: ModuleRevisionId): String = s"${mrid.getOrganisation}:${mrid.getName}:${mrid.getRevision}"
|
private[this] def makeCoords(mrid: ModuleRevisionId): String =
|
||||||
|
s"${mrid.getOrganisation}:${mrid.getName}:${mrid.getRevision}"
|
||||||
|
|
||||||
// We now include the ModuleID in a hash, to ensure that parent-pom transformations don't corrupt child poms.
|
// We now include the ModuleID in a hash, to ensure that parent-pom transformations don't corrupt child poms.
|
||||||
private[this] def MakeTransformHash(md: ModuleDescriptor): String = {
|
private[this] def MakeTransformHash(md: ModuleDescriptor): String = {
|
||||||
|
|
@ -60,7 +92,8 @@ object CustomPomParser {
|
||||||
hash((unqualifiedKeys ++ JarPackagings ++ Set(coords)).toSeq.sorted)
|
hash((unqualifiedKeys ++ JarPackagings ++ Set(coords)).toSeq.sorted)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[this] def hash(ss: Seq[String]): String = Hash.toHex(Hash(ss.flatMap(_ getBytes "UTF-8").toArray))
|
private[this] def hash(ss: Seq[String]): String =
|
||||||
|
Hash.toHex(Hash(ss.flatMap(_ getBytes "UTF-8").toArray))
|
||||||
|
|
||||||
// Unfortunately, ModuleDescriptorParserRegistry is add-only and is a singleton instance.
|
// Unfortunately, ModuleDescriptorParserRegistry is add-only and is a singleton instance.
|
||||||
lazy val registerDefault: Unit = ModuleDescriptorParserRegistry.getInstance.addParser(default)
|
lazy val registerDefault: Unit = ModuleDescriptorParserRegistry.getInstance.addParser(default)
|
||||||
|
|
@ -69,74 +102,93 @@ object CustomPomParser {
|
||||||
if (transformedByThisVersion(md)) md
|
if (transformedByThisVersion(md)) md
|
||||||
else defaultTransformImpl(parser, md)
|
else defaultTransformImpl(parser, md)
|
||||||
|
|
||||||
private[this] def transformedByThisVersion(md: ModuleDescriptor): Boolean =
|
private[this] def transformedByThisVersion(md: ModuleDescriptor): Boolean = {
|
||||||
{
|
val oldTransformedHashKey = "sbtTransformHash"
|
||||||
val oldTransformedHashKey = "sbtTransformHash"
|
val extraInfo = md.getExtraInfo
|
||||||
val extraInfo = md.getExtraInfo
|
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
|
})
|
||||||
})
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private[this] def defaultTransformImpl(parser: ModuleDescriptorParser, md: ModuleDescriptor): ModuleDescriptor =
|
private[this] def defaultTransformImpl(
|
||||||
{
|
parser: ModuleDescriptorParser,
|
||||||
val properties = getPomProperties(md)
|
md: ModuleDescriptor
|
||||||
|
): ModuleDescriptor = {
|
||||||
|
val properties = getPomProperties(md)
|
||||||
|
|
||||||
// Extracts extra attributes (currently, sbt and Scala versions) stored in the <properties> element of the pom.
|
// Extracts extra attributes (currently, sbt and Scala versions) stored in the <properties> element of the pom.
|
||||||
// These are attached to the module itself.
|
// These are attached to the module itself.
|
||||||
val filtered = shouldBeUnqualified(properties)
|
val filtered = shouldBeUnqualified(properties)
|
||||||
|
|
||||||
// Extracts extra attributes for the dependencies.
|
// Extracts extra attributes for the dependencies.
|
||||||
// Because the <dependency> tag in pom.xml cannot include additional metadata,
|
// Because the <dependency> tag in pom.xml cannot include additional metadata,
|
||||||
// sbt includes extra attributes in a 'extraDependencyAttributes' property.
|
// sbt includes extra attributes in a 'extraDependencyAttributes' property.
|
||||||
// This is read/written from/to a pure string (no element structure) because Ivy only
|
// This is read/written from/to a pure string (no element structure) because Ivy only
|
||||||
// parses the immediate text nodes of the property.
|
// parses the immediate text nodes of the property.
|
||||||
val extraDepAttributes = getDependencyExtra(filtered)
|
val extraDepAttributes = getDependencyExtra(filtered)
|
||||||
|
|
||||||
val unqualify = toUnqualify(filtered)
|
val unqualify = toUnqualify(filtered)
|
||||||
|
|
||||||
// Here we always add extra attributes. There's a scenario where parent-pom information corrupts child-poms with "e:" namespaced xml elements
|
// Here we always add extra attributes. There's a scenario where parent-pom information corrupts child-poms with "e:" namespaced xml elements
|
||||||
// and we have to force the every generated xml file to have the appropriate xml namespace
|
// and we have to force the every generated xml file to have the appropriate xml namespace
|
||||||
addExtra(unqualify, extraDepAttributes, parser, md)
|
addExtra(unqualify, extraDepAttributes, parser, md)
|
||||||
}
|
}
|
||||||
// The <properties> element of the pom is used to store additional metadata, such as for sbt plugins or for the base URL for API docs.
|
// The <properties> element of the pom is used to store additional metadata, such as for sbt plugins or for the base URL for API docs.
|
||||||
// This is done because the pom XSD does not appear to allow extra metadata anywhere else.
|
// This is done because the pom XSD does not appear to allow extra metadata anywhere else.
|
||||||
// The extra sbt plugin metadata in pom.xml does not need to be readable by maven, but the other information may be.
|
// The extra sbt plugin metadata in pom.xml does not need to be readable by maven, but the other information may be.
|
||||||
// However, the pom.xml needs to be valid in all cases because other tools like repository managers may read the pom.xml.
|
// However, the pom.xml needs to be valid in all cases because other tools like repository managers may read the pom.xml.
|
||||||
private[sbt] def getPomProperties(md: ModuleDescriptor): Map[String, String] =
|
private[sbt] def getPomProperties(md: ModuleDescriptor): Map[String, String] = {
|
||||||
{
|
import collection.JavaConverters._
|
||||||
import collection.JavaConverters._
|
PomModuleDescriptorBuilder
|
||||||
PomModuleDescriptorBuilder.extractPomProperties(md.getExtraInfo).asInstanceOf[java.util.Map[String, String]].asScala.toMap
|
.extractPomProperties(md.getExtraInfo)
|
||||||
}
|
.asInstanceOf[java.util.Map[String, String]]
|
||||||
|
.asScala
|
||||||
|
.toMap
|
||||||
|
}
|
||||||
private[sbt] def toUnqualify(propertyAttributes: Map[String, String]): Map[String, String] =
|
private[sbt] def toUnqualify(propertyAttributes: Map[String, String]): Map[String, String] =
|
||||||
(propertyAttributes - ExtraAttributesKey) map { case (k, v) => ("e:" + k, v) }
|
(propertyAttributes - ExtraAttributesKey) map { case (k, v) => ("e:" + k, v) }
|
||||||
|
|
||||||
private[this] def shouldBeUnqualified(m: Map[String, String]): Map[String, String] = m.filterKeys(unqualifiedKeys)
|
private[this] def shouldBeUnqualified(m: Map[String, String]): Map[String, String] =
|
||||||
|
m.filterKeys(unqualifiedKeys)
|
||||||
|
|
||||||
private[this] def addExtra(properties: Map[String, String], id: ModuleRevisionId): ModuleRevisionId =
|
private[this] def addExtra(
|
||||||
{
|
properties: Map[String, String],
|
||||||
import collection.JavaConverters._
|
id: ModuleRevisionId
|
||||||
val oldExtra = qualifiedExtra(id)
|
): ModuleRevisionId = {
|
||||||
val newExtra = (oldExtra ++ properties).asJava
|
import collection.JavaConverters._
|
||||||
ModuleRevisionId.newInstance(id.getOrganisation, id.getName, id.getBranch, id.getRevision, newExtra)
|
val oldExtra = qualifiedExtra(id)
|
||||||
}
|
val newExtra = (oldExtra ++ properties).asJava
|
||||||
|
ModuleRevisionId.newInstance(
|
||||||
|
id.getOrganisation,
|
||||||
|
id.getName,
|
||||||
|
id.getBranch,
|
||||||
|
id.getRevision,
|
||||||
|
newExtra
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private[this] def getDependencyExtra(m: Map[String, String]): Map[ModuleRevisionId, Map[String, String]] =
|
private[this] def getDependencyExtra(
|
||||||
|
m: Map[String, String]
|
||||||
|
): Map[ModuleRevisionId, Map[String, String]] =
|
||||||
PomExtraDependencyAttributes.getDependencyExtra(m)
|
PomExtraDependencyAttributes.getDependencyExtra(m)
|
||||||
|
|
||||||
def qualifiedExtra(item: ExtendableItem): Map[String, String] = PomExtraDependencyAttributes.qualifiedExtra(item)
|
def qualifiedExtra(item: ExtendableItem): Map[String, String] =
|
||||||
|
PomExtraDependencyAttributes.qualifiedExtra(item)
|
||||||
def filterCustomExtra(item: ExtendableItem, include: Boolean): Map[String, String] =
|
def filterCustomExtra(item: ExtendableItem, include: Boolean): Map[String, String] =
|
||||||
(qualifiedExtra(item) filterKeys { k => qualifiedIsExtra(k) == include })
|
(qualifiedExtra(item) filterKeys { k =>
|
||||||
|
qualifiedIsExtra(k) == include
|
||||||
|
})
|
||||||
|
|
||||||
def writeDependencyExtra(s: Seq[DependencyDescriptor]): Seq[String] =
|
def writeDependencyExtra(s: Seq[DependencyDescriptor]): Seq[String] =
|
||||||
PomExtraDependencyAttributes.writeDependencyExtra(s)
|
PomExtraDependencyAttributes.writeDependencyExtra(s)
|
||||||
|
|
||||||
// parses the sequence of dependencies with extra attribute information, with one dependency per line
|
// parses the sequence of dependencies with extra attribute information, with one dependency per line
|
||||||
def readDependencyExtra(s: String): Seq[ModuleRevisionId] = PomExtraDependencyAttributes.readDependencyExtra(s)
|
def readDependencyExtra(s: String): Seq[ModuleRevisionId] =
|
||||||
|
PomExtraDependencyAttributes.readDependencyExtra(s)
|
||||||
|
|
||||||
def qualifiedIsExtra(k: String): Boolean = PomExtraDependencyAttributes.qualifiedIsExtra(k)
|
def qualifiedIsExtra(k: String): Boolean = PomExtraDependencyAttributes.qualifiedIsExtra(k)
|
||||||
|
|
||||||
|
|
@ -145,20 +197,33 @@ object CustomPomParser {
|
||||||
// with the extra attributes from the <properties> section
|
// with the extra attributes from the <properties> section
|
||||||
def simplify(id: ModuleRevisionId): ModuleRevisionId = PomExtraDependencyAttributes.simplify(id)
|
def simplify(id: ModuleRevisionId): ModuleRevisionId = PomExtraDependencyAttributes.simplify(id)
|
||||||
|
|
||||||
private[this] def addExtra(dep: DependencyDescriptor, extra: Map[ModuleRevisionId, Map[String, String]]): DependencyDescriptor =
|
private[this] def addExtra(
|
||||||
{
|
dep: DependencyDescriptor,
|
||||||
val extras = if (extra.isEmpty) None else extra get simplify(dep.getDependencyRevisionId)
|
extra: Map[ModuleRevisionId, Map[String, String]]
|
||||||
extras match {
|
): DependencyDescriptor = {
|
||||||
case None => dep
|
val extras = if (extra.isEmpty) None else extra get simplify(dep.getDependencyRevisionId)
|
||||||
case Some(extraAttrs) => transform(dep, revId => addExtra(extraAttrs, revId))
|
extras match {
|
||||||
}
|
case None => dep
|
||||||
|
case Some(extraAttrs) => transform(dep, revId => addExtra(extraAttrs, revId))
|
||||||
}
|
}
|
||||||
private[this] def transform(dep: DependencyDescriptor, f: ModuleRevisionId => ModuleRevisionId): DependencyDescriptor =
|
}
|
||||||
DefaultDependencyDescriptor.transformInstance(dep, namespaceTransformer(dep.getDependencyRevisionId, f), false)
|
private[this] def transform(
|
||||||
|
dep: DependencyDescriptor,
|
||||||
|
f: ModuleRevisionId => ModuleRevisionId
|
||||||
|
): DependencyDescriptor =
|
||||||
|
DefaultDependencyDescriptor.transformInstance(
|
||||||
|
dep,
|
||||||
|
namespaceTransformer(dep.getDependencyRevisionId, f),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
private[this] def namespaceTransformer(txId: ModuleRevisionId, f: ModuleRevisionId => ModuleRevisionId): NamespaceTransformer =
|
private[this] def namespaceTransformer(
|
||||||
|
txId: ModuleRevisionId,
|
||||||
|
f: ModuleRevisionId => ModuleRevisionId
|
||||||
|
): NamespaceTransformer =
|
||||||
new NamespaceTransformer {
|
new NamespaceTransformer {
|
||||||
def transform(revId: ModuleRevisionId): ModuleRevisionId = if (revId == txId) f(revId) else revId
|
def transform(revId: ModuleRevisionId): ModuleRevisionId =
|
||||||
|
if (revId == txId) f(revId) else revId
|
||||||
def isIdentity = false
|
def isIdentity = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,53 +232,80 @@ object CustomPomParser {
|
||||||
VersionRange.stripMavenVersionRange(dd.getDependencyRevisionId.getRevision) match {
|
VersionRange.stripMavenVersionRange(dd.getDependencyRevisionId.getRevision) match {
|
||||||
case Some(newVersion) =>
|
case Some(newVersion) =>
|
||||||
val id = dd.getDependencyRevisionId
|
val id = dd.getDependencyRevisionId
|
||||||
val newId = ModuleRevisionId.newInstance(id.getOrganisation, id.getName, id.getBranch, newVersion, id.getExtraAttributes)
|
val newId = ModuleRevisionId.newInstance(
|
||||||
|
id.getOrganisation,
|
||||||
|
id.getName,
|
||||||
|
id.getBranch,
|
||||||
|
newVersion,
|
||||||
|
id.getExtraAttributes
|
||||||
|
)
|
||||||
transform(dd, _ => newId)
|
transform(dd, _ => newId)
|
||||||
case None => dd
|
case None => dd
|
||||||
}
|
}
|
||||||
private[sbt] lazy val versionRangeFlag = sys.props.get("sbt.modversionrange") map { _.toLowerCase == "true" } getOrElse true
|
private[sbt] lazy val versionRangeFlag = sys.props.get("sbt.modversionrange") map {
|
||||||
|
_.toLowerCase == "true"
|
||||||
|
} getOrElse true
|
||||||
|
|
||||||
import collection.JavaConverters._
|
import collection.JavaConverters._
|
||||||
def addExtra(properties: Map[String, String], dependencyExtra: Map[ModuleRevisionId, Map[String, String]], parser: ModuleDescriptorParser, md: ModuleDescriptor): ModuleDescriptor =
|
def addExtra(
|
||||||
{
|
properties: Map[String, String],
|
||||||
val dmd = new DefaultModuleDescriptor(parser, md.getResource)
|
dependencyExtra: Map[ModuleRevisionId, Map[String, String]],
|
||||||
|
parser: ModuleDescriptorParser,
|
||||||
|
md: ModuleDescriptor
|
||||||
|
): ModuleDescriptor = {
|
||||||
|
val dmd = new DefaultModuleDescriptor(parser, md.getResource)
|
||||||
|
|
||||||
val mrid = addExtra(properties, md.getModuleRevisionId)
|
val mrid = addExtra(properties, md.getModuleRevisionId)
|
||||||
val resolvedMrid = addExtra(properties, md.getResolvedModuleRevisionId)
|
val resolvedMrid = addExtra(properties, md.getResolvedModuleRevisionId)
|
||||||
dmd.setModuleRevisionId(mrid)
|
dmd.setModuleRevisionId(mrid)
|
||||||
dmd.setResolvedModuleRevisionId(resolvedMrid)
|
dmd.setResolvedModuleRevisionId(resolvedMrid)
|
||||||
|
|
||||||
dmd.setDefault(md.isDefault)
|
dmd.setDefault(md.isDefault)
|
||||||
dmd.setHomePage(md.getHomePage)
|
dmd.setHomePage(md.getHomePage)
|
||||||
dmd.setDescription(md.getDescription)
|
dmd.setDescription(md.getDescription)
|
||||||
dmd.setLastModified(md.getLastModified)
|
dmd.setLastModified(md.getLastModified)
|
||||||
dmd.setStatus(md.getStatus())
|
dmd.setStatus(md.getStatus())
|
||||||
dmd.setPublicationDate(md.getPublicationDate())
|
dmd.setPublicationDate(md.getPublicationDate())
|
||||||
dmd.setResolvedPublicationDate(md.getResolvedPublicationDate())
|
dmd.setResolvedPublicationDate(md.getResolvedPublicationDate())
|
||||||
|
|
||||||
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) dmd.addExtraInfo(key, value)
|
for ((key, value) <- md.getExtraInfo.asInstanceOf[java.util.Map[String, String]].asScala)
|
||||||
dmd.addExtraInfo(TransformedHashKey, MakeTransformHash(md)) // mark as transformed by this version, so we don't need to do it again
|
dmd.addExtraInfo(key, value)
|
||||||
for ((key, value) <- md.getExtraAttributesNamespaces.asInstanceOf[java.util.Map[String, String]].asScala) dmd.addExtraAttributeNamespace(key, value)
|
dmd.addExtraInfo(TransformedHashKey, MakeTransformHash(md)) // mark as transformed by this version, so we don't need to do it again
|
||||||
IvySbt.addExtraNamespace(dmd)
|
for ((key, value) <- md.getExtraAttributesNamespaces
|
||||||
|
.asInstanceOf[java.util.Map[String, String]]
|
||||||
|
.asScala) dmd.addExtraAttributeNamespace(key, value)
|
||||||
|
IvySbt.addExtraNamespace(dmd)
|
||||||
|
|
||||||
val withExtra = md.getDependencies map { dd => addExtra(dd, dependencyExtra) }
|
val withExtra = md.getDependencies map { dd =>
|
||||||
val withVersionRangeMod: Seq[DependencyDescriptor] =
|
addExtra(dd, dependencyExtra)
|
||||||
if (versionRangeFlag) withExtra map { stripVersionRange }
|
|
||||||
else withExtra
|
|
||||||
val unique = IvySbt.mergeDuplicateDefinitions(withVersionRangeMod)
|
|
||||||
unique foreach dmd.addDependency
|
|
||||||
|
|
||||||
for (ed <- md.getInheritedDescriptors) dmd.addInheritedDescriptor(new DefaultExtendsDescriptor(md, ed.getLocation, ed.getExtendsTypes))
|
|
||||||
for (conf <- md.getConfigurations) {
|
|
||||||
dmd.addConfiguration(conf)
|
|
||||||
for (art <- md.getArtifacts(conf.getName)) {
|
|
||||||
val ext = art.getExt
|
|
||||||
val newExt = if (JarPackagings(ext)) "jar" else ext
|
|
||||||
val nart = new DefaultArtifact(mrid, art.getPublicationDate, art.getName, art.getType, newExt, art.getUrl, art.getQualifiedExtraAttributes)
|
|
||||||
dmd.addArtifact(conf.getName, nart)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dmd
|
|
||||||
}
|
}
|
||||||
|
val withVersionRangeMod: Seq[DependencyDescriptor] =
|
||||||
|
if (versionRangeFlag) withExtra map { stripVersionRange } else withExtra
|
||||||
|
val unique = IvySbt.mergeDuplicateDefinitions(withVersionRangeMod)
|
||||||
|
unique foreach dmd.addDependency
|
||||||
|
|
||||||
|
for (ed <- md.getInheritedDescriptors)
|
||||||
|
dmd.addInheritedDescriptor(
|
||||||
|
new DefaultExtendsDescriptor(md, ed.getLocation, ed.getExtendsTypes)
|
||||||
|
)
|
||||||
|
for (conf <- md.getConfigurations) {
|
||||||
|
dmd.addConfiguration(conf)
|
||||||
|
for (art <- md.getArtifacts(conf.getName)) {
|
||||||
|
val ext = art.getExt
|
||||||
|
val newExt = if (JarPackagings(ext)) "jar" else ext
|
||||||
|
val nart = new DefaultArtifact(
|
||||||
|
mrid,
|
||||||
|
art.getPublicationDate,
|
||||||
|
art.getName,
|
||||||
|
art.getType,
|
||||||
|
newExt,
|
||||||
|
art.getUrl,
|
||||||
|
art.getQualifiedExtraAttributes
|
||||||
|
)
|
||||||
|
dmd.addArtifact(conf.getName, nart)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dmd
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@ package sbt.internal.librarymanagement
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
import org.apache.ivy.core.module.descriptor.{ DefaultDependencyDescriptor, DefaultModuleDescriptor }
|
import org.apache.ivy.core.module.descriptor.{
|
||||||
|
DefaultDependencyDescriptor,
|
||||||
|
DefaultModuleDescriptor
|
||||||
|
}
|
||||||
import org.apache.ivy.core.settings.IvySettings
|
import org.apache.ivy.core.settings.IvySettings
|
||||||
import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser
|
import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser
|
||||||
import org.apache.ivy.plugins.repository.Resource
|
import org.apache.ivy.plugins.repository.Resource
|
||||||
|
|
@ -15,21 +18,22 @@ 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]) extends Parser(CustomXmlParser, settings) {
|
class CustomParser(settings: IvySettings, defaultConfig: Option[String])
|
||||||
def setSource(url: URL) =
|
extends Parser(CustomXmlParser, settings) {
|
||||||
{
|
def setSource(url: URL) = {
|
||||||
super.setResource(new URLResource(url))
|
super.setResource(new URLResource(url))
|
||||||
super.setInput(url)
|
super.setInput(url)
|
||||||
}
|
}
|
||||||
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)
|
if (defaultConfig.isDefined) setDefaultConfMapping("*->default(compile)")
|
||||||
if (defaultConfig.isDefined) setDefaultConfMapping("*->default(compile)")
|
}
|
||||||
}
|
override def parseDepsConfs(confs: String, dd: DefaultDependencyDescriptor) =
|
||||||
override def parseDepsConfs(confs: String, dd: DefaultDependencyDescriptor) = super.parseDepsConfs(confs, dd)
|
super.parseDepsConfs(confs, dd)
|
||||||
override def getDefaultConf = defaultConfig.getOrElse(super.getDefaultConf)
|
override def getDefaultConf = defaultConfig.getOrElse(super.getDefaultConf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,14 @@ import java.net.URL
|
||||||
|
|
||||||
import org.apache.ivy.core.cache.ArtifactOrigin
|
import org.apache.ivy.core.cache.ArtifactOrigin
|
||||||
import org.apache.ivy.core.cache.{ DefaultRepositoryCacheManager, RepositoryCacheManager }
|
import org.apache.ivy.core.cache.{ DefaultRepositoryCacheManager, RepositoryCacheManager }
|
||||||
import org.apache.ivy.core.module.descriptor.{ Artifact => IvyArtifact, DefaultArtifact, DefaultDependencyArtifactDescriptor, DefaultModuleDescriptor, DependencyArtifactDescriptor, DependencyDescriptor }
|
import org.apache.ivy.core.module.descriptor.{
|
||||||
|
Artifact => IvyArtifact,
|
||||||
|
DefaultArtifact,
|
||||||
|
DefaultDependencyArtifactDescriptor,
|
||||||
|
DefaultModuleDescriptor,
|
||||||
|
DependencyArtifactDescriptor,
|
||||||
|
DependencyDescriptor
|
||||||
|
}
|
||||||
import org.apache.ivy.core.module.id.ModuleRevisionId
|
import org.apache.ivy.core.module.id.ModuleRevisionId
|
||||||
import org.apache.ivy.core.report.ArtifactDownloadReport
|
import org.apache.ivy.core.report.ArtifactDownloadReport
|
||||||
import org.apache.ivy.core.report.{ DownloadReport, DownloadStatus }
|
import org.apache.ivy.core.report.{ DownloadReport, DownloadStatus }
|
||||||
|
|
@ -22,7 +29,8 @@ import FakeResolver._
|
||||||
/**
|
/**
|
||||||
* A fake `DependencyResolver` that statically serves predefined artifacts.
|
* A fake `DependencyResolver` that statically serves predefined artifacts.
|
||||||
*/
|
*/
|
||||||
private[sbt] class FakeResolver(private var name: String, cacheDir: File, modules: ModulesMap) extends DependencyResolver {
|
private[sbt] class FakeResolver(private var name: String, cacheDir: File, modules: ModulesMap)
|
||||||
|
extends DependencyResolver {
|
||||||
|
|
||||||
private object Artifact {
|
private object Artifact {
|
||||||
def unapply(art: IvyArtifact): Some[(String, String, String)] = {
|
def unapply(art: IvyArtifact): Some[(String, String, String)] = {
|
||||||
|
|
@ -55,7 +63,10 @@ private[sbt] class FakeResolver(private var name: String, cacheDir: File, module
|
||||||
override def commitPublishTransaction(): Unit =
|
override def commitPublishTransaction(): Unit =
|
||||||
throw new UnsupportedOperationException("This resolver doesn't support publishing.")
|
throw new UnsupportedOperationException("This resolver doesn't support publishing.")
|
||||||
|
|
||||||
override def download(artifact: ArtifactOrigin, options: DownloadOptions): ArtifactDownloadReport = {
|
override def download(
|
||||||
|
artifact: ArtifactOrigin,
|
||||||
|
options: DownloadOptions
|
||||||
|
): ArtifactDownloadReport = {
|
||||||
|
|
||||||
val report = new ArtifactDownloadReport(artifact.getArtifact)
|
val report = new ArtifactDownloadReport(artifact.getArtifact)
|
||||||
val path = new URL(artifact.getLocation).toURI.getPath
|
val path = new URL(artifact.getLocation).toURI.getPath
|
||||||
|
|
@ -99,12 +110,12 @@ private[sbt] class FakeResolver(private var name: String, cacheDir: File, module
|
||||||
val mrid = dd.getDependencyRevisionId()
|
val mrid = dd.getDependencyRevisionId()
|
||||||
|
|
||||||
val artifact = modules get ((organisation, name, revision)) map { arts =>
|
val artifact = modules get ((organisation, name, revision)) map { arts =>
|
||||||
|
|
||||||
val artifacts: Array[DependencyArtifactDescriptor] = arts.toArray map (_ artifactOf dd)
|
val artifacts: Array[DependencyArtifactDescriptor] = arts.toArray map (_ artifactOf dd)
|
||||||
val moduleDescriptor = DefaultModuleDescriptor.newDefaultInstance(mrid, artifacts)
|
val moduleDescriptor = DefaultModuleDescriptor.newDefaultInstance(mrid, artifacts)
|
||||||
val defaultArtifact = arts.headOption match {
|
val defaultArtifact = arts.headOption match {
|
||||||
case Some(FakeArtifact(name, tpe, ext, _)) => new DefaultArtifact(mrid, new java.util.Date, name, tpe, ext)
|
case Some(FakeArtifact(name, tpe, ext, _)) =>
|
||||||
case None => null
|
new DefaultArtifact(mrid, new java.util.Date, name, tpe, ext)
|
||||||
|
case None => null
|
||||||
}
|
}
|
||||||
val metadataReport = new MetadataArtifactDownloadReport(defaultArtifact)
|
val metadataReport = new MetadataArtifactDownloadReport(defaultArtifact)
|
||||||
metadataReport.setDownloadStatus(DownloadStatus.SUCCESSFUL)
|
metadataReport.setDownloadStatus(DownloadStatus.SUCCESSFUL)
|
||||||
|
|
@ -147,10 +158,16 @@ private[sbt] class FakeResolver(private var name: String, cacheDir: File, module
|
||||||
new RevisionEntry(module, v)
|
new RevisionEntry(module, v)
|
||||||
}.toArray
|
}.toArray
|
||||||
|
|
||||||
override def listTokenValues(tokens: Array[String], criteria: java.util.Map[_, _]): Array[java.util.Map[_, _]] =
|
override def listTokenValues(
|
||||||
|
tokens: Array[String],
|
||||||
|
criteria: java.util.Map[_, _]
|
||||||
|
): Array[java.util.Map[_, _]] =
|
||||||
Array.empty
|
Array.empty
|
||||||
|
|
||||||
override def listTokenValues(token: String, otherTokenValues: java.util.Map[_, _]): Array[String] =
|
override def listTokenValues(
|
||||||
|
token: String,
|
||||||
|
otherTokenValues: java.util.Map[_, _]
|
||||||
|
): Array[String] =
|
||||||
Array.empty
|
Array.empty
|
||||||
|
|
||||||
override def locate(art: IvyArtifact): ArtifactOrigin = {
|
override def locate(art: IvyArtifact): ArtifactOrigin = {
|
||||||
|
|
@ -158,7 +175,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 (a => a.name == art.getName && a.tpe == art.getType && a.ext == art.getExt)
|
artifact <- artifacts find (a =>
|
||||||
|
a.name == art.getName && a.tpe == art.getType && a.ext == art.getExt)
|
||||||
} yield new ArtifactOrigin(art, /* isLocal = */ true, artifact.file.toURI.toURL.toString)
|
} yield new ArtifactOrigin(art, /* isLocal = */ true, artifact.file.toURI.toURL.toString)
|
||||||
|
|
||||||
artifact.orNull
|
artifact.orNull
|
||||||
|
|
@ -183,6 +201,13 @@ private[sbt] object FakeResolver {
|
||||||
|
|
||||||
final case class FakeArtifact(name: String, tpe: String, ext: String, file: File) {
|
final case class FakeArtifact(name: String, tpe: String, ext: String, file: File) {
|
||||||
def artifactOf(dd: DependencyDescriptor): DependencyArtifactDescriptor =
|
def artifactOf(dd: DependencyDescriptor): DependencyArtifactDescriptor =
|
||||||
new DefaultDependencyArtifactDescriptor(dd, name, tpe, ext, file.toURI.toURL, new java.util.HashMap)
|
new DefaultDependencyArtifactDescriptor(
|
||||||
|
dd,
|
||||||
|
name,
|
||||||
|
tpe,
|
||||||
|
ext,
|
||||||
|
file.toURI.toURL,
|
||||||
|
new java.util.HashMap
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -12,7 +12,12 @@ import org.apache.ivy.Ivy
|
||||||
import org.apache.ivy.core.{ IvyPatternHelper, LogOptions }
|
import org.apache.ivy.core.{ IvyPatternHelper, LogOptions }
|
||||||
import org.apache.ivy.core.deliver.DeliverOptions
|
import org.apache.ivy.core.deliver.DeliverOptions
|
||||||
import org.apache.ivy.core.install.InstallOptions
|
import org.apache.ivy.core.install.InstallOptions
|
||||||
import org.apache.ivy.core.module.descriptor.{ Artifact => IArtifact, MDArtifact, ModuleDescriptor, DefaultModuleDescriptor }
|
import org.apache.ivy.core.module.descriptor.{
|
||||||
|
Artifact => IArtifact,
|
||||||
|
MDArtifact,
|
||||||
|
ModuleDescriptor,
|
||||||
|
DefaultModuleDescriptor
|
||||||
|
}
|
||||||
import org.apache.ivy.core.report.ResolveReport
|
import org.apache.ivy.core.report.ResolveReport
|
||||||
import org.apache.ivy.core.resolve.ResolveOptions
|
import org.apache.ivy.core.resolve.ResolveOptions
|
||||||
import org.apache.ivy.plugins.resolver.{ BasicResolver, DependencyResolver }
|
import org.apache.ivy.plugins.resolver.{ BasicResolver, DependencyResolver }
|
||||||
|
|
@ -21,20 +26,59 @@ import sbt.util.{ Logger, ShowLines }
|
||||||
import sbt.internal.util.{ SourcePosition, LinePosition, RangePosition, LineRange }
|
import sbt.internal.util.{ SourcePosition, LinePosition, RangePosition, LineRange }
|
||||||
import sbt.librarymanagement._, syntax._
|
import sbt.librarymanagement._, syntax._
|
||||||
|
|
||||||
final class DeliverConfiguration(val deliverIvyPattern: String, val status: String, val configurations: Option[Vector[Configuration]], val logging: UpdateLogging)
|
final class DeliverConfiguration(
|
||||||
final class PublishConfiguration(val ivyFile: Option[File], val resolverName: String, val artifacts: Map[Artifact, File], val checksums: Vector[String], val logging: UpdateLogging,
|
val deliverIvyPattern: String,
|
||||||
val overwrite: Boolean) {
|
val status: String,
|
||||||
def this(ivyFile: Option[File], resolverName: String, artifacts: Map[Artifact, File], checksums: Vector[String], logging: UpdateLogging) =
|
val configurations: Option[Vector[Configuration]],
|
||||||
|
val logging: UpdateLogging
|
||||||
|
)
|
||||||
|
final class PublishConfiguration(
|
||||||
|
val ivyFile: Option[File],
|
||||||
|
val resolverName: String,
|
||||||
|
val artifacts: Map[Artifact, File],
|
||||||
|
val checksums: Vector[String],
|
||||||
|
val logging: UpdateLogging,
|
||||||
|
val overwrite: Boolean
|
||||||
|
) {
|
||||||
|
def this(
|
||||||
|
ivyFile: Option[File],
|
||||||
|
resolverName: String,
|
||||||
|
artifacts: Map[Artifact, File],
|
||||||
|
checksums: Vector[String],
|
||||||
|
logging: UpdateLogging
|
||||||
|
) =
|
||||||
this(ivyFile, resolverName, artifacts, checksums, logging, false)
|
this(ivyFile, resolverName, artifacts, checksums, logging, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
final case class MakePomConfiguration(file: File, moduleInfo: ModuleInfo, configurations: Option[Vector[Configuration]] = None, extra: NodeSeq = NodeSeq.Empty, process: XNode => XNode = n => n, filterRepositories: MavenRepository => Boolean = _ => true, allRepositories: Boolean, includeTypes: Set[String] = Set(Artifact.DefaultType, Artifact.PomType))
|
final case class MakePomConfiguration(
|
||||||
|
file: File,
|
||||||
|
moduleInfo: ModuleInfo,
|
||||||
|
configurations: Option[Vector[Configuration]] = None,
|
||||||
|
extra: NodeSeq = NodeSeq.Empty,
|
||||||
|
process: XNode => XNode = n => n,
|
||||||
|
filterRepositories: MavenRepository => Boolean = _ => true,
|
||||||
|
allRepositories: Boolean,
|
||||||
|
includeTypes: Set[String] = Set(Artifact.DefaultType, Artifact.PomType)
|
||||||
|
)
|
||||||
|
|
||||||
/** @param exclude is a map from ModuleID to classifiers that were previously tried and failed, so should now be excluded */
|
/** @param exclude is a map from ModuleID to classifiers that were previously tried and failed, so should now be excluded */
|
||||||
final case class GetClassifiersConfiguration(module: GetClassifiersModule, exclude: Map[ModuleID, Set[String]], configuration: UpdateConfiguration, ivyScala: Option[IvyScala], sourceArtifactTypes: Set[String], docArtifactTypes: Set[String])
|
final case class GetClassifiersConfiguration(
|
||||||
final case class GetClassifiersModule(id: ModuleID, modules: Vector[ModuleID], configurations: Vector[Configuration], classifiers: Vector[String])
|
module: GetClassifiersModule,
|
||||||
|
exclude: Map[ModuleID, Set[String]],
|
||||||
|
configuration: UpdateConfiguration,
|
||||||
|
ivyScala: Option[IvyScala],
|
||||||
|
sourceArtifactTypes: Set[String],
|
||||||
|
docArtifactTypes: Set[String]
|
||||||
|
)
|
||||||
|
final case class GetClassifiersModule(
|
||||||
|
id: ModuleID,
|
||||||
|
modules: Vector[ModuleID],
|
||||||
|
configurations: Vector[Configuration],
|
||||||
|
classifiers: Vector[String]
|
||||||
|
)
|
||||||
|
|
||||||
final class UnresolvedWarningConfiguration private[sbt] (
|
final class UnresolvedWarningConfiguration private[sbt] (
|
||||||
val modulePositions: Map[ModuleID, SourcePosition]
|
val modulePositions: Map[ModuleID, SourcePosition]
|
||||||
)
|
)
|
||||||
object UnresolvedWarningConfiguration {
|
object UnresolvedWarningConfiguration {
|
||||||
def apply(): UnresolvedWarningConfiguration = apply(Map())
|
def apply(): UnresolvedWarningConfiguration = apply(Map())
|
||||||
|
|
@ -43,6 +87,7 @@ object UnresolvedWarningConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
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, default) =>
|
module.withModule(log) { (ivy, md, default) =>
|
||||||
|
|
@ -73,27 +118,48 @@ object IvyActions {
|
||||||
|
|
||||||
/** Creates a Maven pom from the given Ivy configuration*/
|
/** Creates a Maven pom from the given Ivy configuration*/
|
||||||
def makePom(module: IvySbt#Module, configuration: MakePomConfiguration, log: Logger): Unit = {
|
def makePom(module: IvySbt#Module, configuration: MakePomConfiguration, log: Logger): Unit = {
|
||||||
import configuration.{ allRepositories, moduleInfo, configurations, extra, file, filterRepositories, process, includeTypes }
|
import configuration.{
|
||||||
|
allRepositories,
|
||||||
|
moduleInfo,
|
||||||
|
configurations,
|
||||||
|
extra,
|
||||||
|
file,
|
||||||
|
filterRepositories,
|
||||||
|
process,
|
||||||
|
includeTypes
|
||||||
|
}
|
||||||
module.withModule(log) { (ivy, md, default) =>
|
module.withModule(log) { (ivy, md, default) =>
|
||||||
(new MakePom(log)).write(ivy, md, moduleInfo, configurations, includeTypes, extra, process, filterRepositories, allRepositories, file)
|
(new MakePom(log)).write(
|
||||||
|
ivy,
|
||||||
|
md,
|
||||||
|
moduleInfo,
|
||||||
|
configurations,
|
||||||
|
includeTypes,
|
||||||
|
extra,
|
||||||
|
process,
|
||||||
|
filterRepositories,
|
||||||
|
allRepositories,
|
||||||
|
file
|
||||||
|
)
|
||||||
log.info("Wrote " + file.getAbsolutePath)
|
log.info("Wrote " + file.getAbsolutePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def deliver(module: IvySbt#Module, configuration: DeliverConfiguration, log: Logger): File =
|
def deliver(module: IvySbt#Module, configuration: DeliverConfiguration, log: Logger): File = {
|
||||||
{
|
import configuration._
|
||||||
import configuration._
|
module.withModule(log) {
|
||||||
module.withModule(log) {
|
case (ivy, md, default) =>
|
||||||
case (ivy, md, default) =>
|
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(IvySbt.getConfigurations(md, configurations))
|
||||||
options.setConfs(IvySbt.getConfigurations(md, configurations))
|
ivy.deliver(revID, revID.getRevision, deliverIvyPattern, options)
|
||||||
ivy.deliver(revID, revID.getRevision, deliverIvyPattern, options)
|
deliveredFile(ivy, deliverIvyPattern, md)
|
||||||
deliveredFile(ivy, deliverIvyPattern, md)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
def deliveredFile(ivy: Ivy, pattern: String, md: ModuleDescriptor): File =
|
def deliveredFile(ivy: Ivy, pattern: String, md: ModuleDescriptor): File =
|
||||||
ivy.getSettings.resolveFile(IvyPatternHelper.substitute(pattern, md.getResolvedModuleRevisionId))
|
ivy.getSettings.resolveFile(
|
||||||
|
IvyPatternHelper.substitute(pattern, md.getResolvedModuleRevisionId)
|
||||||
|
)
|
||||||
|
|
||||||
def publish(module: IvySbt#Module, configuration: PublishConfiguration, log: Logger): Unit = {
|
def publish(module: IvySbt#Module, configuration: PublishConfiguration, log: Logger): Unit = {
|
||||||
import configuration._
|
import configuration._
|
||||||
|
|
@ -101,40 +167,59 @@ object IvyActions {
|
||||||
case (ivy, md, default) =>
|
case (ivy, md, default) =>
|
||||||
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 => (MDArtifact.newIvyArtifact(md), file) }
|
val ivyArtifact = ivyFile map { 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) { publish(md, as, resolver, overwrite = overwrite) }
|
withChecksums(resolver, checksums) { publish(md, as, resolver, overwrite = overwrite) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private[this] def withChecksums[T](resolver: DependencyResolver, checksums: Vector[String])(act: => T): T =
|
private[this] def withChecksums[T](resolver: DependencyResolver, checksums: Vector[String])(
|
||||||
|
act: => T
|
||||||
|
): T =
|
||||||
resolver match { case br: BasicResolver => withChecksums(br, checksums)(act); case _ => act }
|
resolver match { case br: BasicResolver => withChecksums(br, checksums)(act); case _ => act }
|
||||||
private[this] def withChecksums[T](resolver: BasicResolver, checksums: Vector[String])(act: => T): T =
|
private[this] def withChecksums[T](resolver: BasicResolver, checksums: Vector[String])(
|
||||||
{
|
act: => T
|
||||||
val previous = resolver.getChecksumAlgorithms
|
): T = {
|
||||||
resolver.setChecksums(checksums mkString ",")
|
val previous = resolver.getChecksumAlgorithms
|
||||||
try { act }
|
resolver.setChecksums(checksums mkString ",")
|
||||||
finally { resolver.setChecksums(previous mkString ",") }
|
try { act } finally { resolver.setChecksums(previous mkString ",") }
|
||||||
}
|
}
|
||||||
private def crossVersionMap(moduleSettings: ModuleSettings): Option[String => String] =
|
private def crossVersionMap(moduleSettings: ModuleSettings): Option[String => String] =
|
||||||
moduleSettings match {
|
moduleSettings match {
|
||||||
case i: InlineConfiguration => CrossVersion(i.module, i.ivyScala)
|
case i: InlineConfiguration => CrossVersion(i.module, i.ivyScala)
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
}
|
||||||
def mapArtifacts(module: ModuleDescriptor, cross: Option[String => String], artifacts: Map[Artifact, File]): Vector[(IArtifact, File)] =
|
def mapArtifacts(
|
||||||
{
|
module: ModuleDescriptor,
|
||||||
val rawa = artifacts.keys.toVector
|
cross: Option[String => String],
|
||||||
val seqa = CrossVersion.substituteCross(rawa, cross)
|
artifacts: Map[Artifact, File]
|
||||||
val zipped = rawa zip IvySbt.mapArtifacts(module, seqa)
|
): Vector[(IArtifact, File)] = {
|
||||||
zipped map { case (a, ivyA) => (ivyA, artifacts(a)) }
|
val rawa = artifacts.keys.toVector
|
||||||
}
|
val seqa = CrossVersion.substituteCross(rawa, cross)
|
||||||
|
val zipped = rawa zip IvySbt.mapArtifacts(module, seqa)
|
||||||
|
zipped map { case (a, ivyA) => (ivyA, artifacts(a)) }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves and retrieves dependencies. 'ivyConfig' is used to produce an Ivy file and configuration.
|
* Resolves and retrieves dependencies. 'ivyConfig' is used to produce an Ivy file and configuration.
|
||||||
* 'updateConfig' configures the actual resolution and retrieval process.
|
* 'updateConfig' configures the actual resolution and retrieval process.
|
||||||
*/
|
*/
|
||||||
@deprecated("This is no longer public.", "0.13.6")
|
@deprecated("This is no longer public.", "0.13.6")
|
||||||
def update(module: IvySbt#Module, configuration: UpdateConfiguration, log: Logger): UpdateReport =
|
def update(
|
||||||
updateEither(module, configuration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, log) match {
|
module: IvySbt#Module,
|
||||||
|
configuration: UpdateConfiguration,
|
||||||
|
log: Logger
|
||||||
|
): UpdateReport =
|
||||||
|
updateEither(
|
||||||
|
module,
|
||||||
|
configuration,
|
||||||
|
UnresolvedWarningConfiguration(),
|
||||||
|
LogicalClock.unknown,
|
||||||
|
None,
|
||||||
|
log
|
||||||
|
) match {
|
||||||
case Right(r) => r
|
case Right(r) => r
|
||||||
case Left(w) =>
|
case Left(w) =>
|
||||||
throw w.resolveException
|
throw w.resolveException
|
||||||
|
|
@ -144,10 +229,17 @@ object IvyActions {
|
||||||
* Resolves and retrieves dependencies. 'ivyConfig' is used to produce an Ivy file and configuration.
|
* Resolves and retrieves dependencies. 'ivyConfig' is used to produce an Ivy file and configuration.
|
||||||
* 'updateConfig' configures the actual resolution and retrieval process.
|
* 'updateConfig' configures the actual resolution and retrieval process.
|
||||||
*/
|
*/
|
||||||
private[sbt] def updateEither(module: IvySbt#Module, configuration: UpdateConfiguration,
|
private[sbt] def updateEither(
|
||||||
uwconfig: UnresolvedWarningConfiguration, logicalClock: LogicalClock, depDir: Option[File], log: Logger): Either[UnresolvedWarning, UpdateReport] =
|
module: IvySbt#Module,
|
||||||
|
configuration: UpdateConfiguration,
|
||||||
|
uwconfig: UnresolvedWarningConfiguration,
|
||||||
|
logicalClock: LogicalClock,
|
||||||
|
depDir: Option[File],
|
||||||
|
log: Logger
|
||||||
|
): Either[UnresolvedWarning, UpdateReport] =
|
||||||
module.withModule(log) {
|
module.withModule(log) {
|
||||||
case (ivy, md, default) if module.owner.configuration.updateOptions.cachedResolution && depDir.isDefined =>
|
case (ivy, md, default)
|
||||||
|
if module.owner.configuration.updateOptions.cachedResolution && depDir.isDefined =>
|
||||||
ivy.getResolveEngine match {
|
ivy.getResolveEngine match {
|
||||||
case x: CachedResolutionResolveEngine =>
|
case x: CachedResolutionResolveEngine =>
|
||||||
val iw = IvySbt.inconsistentDuplicateWarning(md)
|
val iw = IvySbt.inconsistentDuplicateWarning(md)
|
||||||
|
|
@ -157,7 +249,16 @@ object IvyActions {
|
||||||
resolveOptions.setResolveId(resolveId)
|
resolveOptions.setResolveId(resolveId)
|
||||||
resolveOptions.setArtifactFilter(configuration.artifactFilter)
|
resolveOptions.setArtifactFilter(configuration.artifactFilter)
|
||||||
resolveOptions.setLog(ivyLogLevel(configuration.logging))
|
resolveOptions.setLog(ivyLogLevel(configuration.logging))
|
||||||
x.customResolve(md, configuration.missingOk, logicalClock, resolveOptions, depDir getOrElse { sys.error("dependency base directory is not specified") }, log) match {
|
x.customResolve(
|
||||||
|
md,
|
||||||
|
configuration.missingOk,
|
||||||
|
logicalClock,
|
||||||
|
resolveOptions,
|
||||||
|
depDir getOrElse {
|
||||||
|
sys.error("dependency base directory is not specified")
|
||||||
|
},
|
||||||
|
log
|
||||||
|
) match {
|
||||||
case Left(x) =>
|
case Left(x) =>
|
||||||
Left(UnresolvedWarning(x, uwconfig))
|
Left(UnresolvedWarning(x, uwconfig))
|
||||||
case Right(uReport) =>
|
case Right(uReport) =>
|
||||||
|
|
@ -170,12 +271,14 @@ object IvyActions {
|
||||||
case (ivy, md, default) =>
|
case (ivy, md, default) =>
|
||||||
val iw = IvySbt.inconsistentDuplicateWarning(md)
|
val iw = IvySbt.inconsistentDuplicateWarning(md)
|
||||||
iw foreach { log.warn(_) }
|
iw foreach { log.warn(_) }
|
||||||
val (report, err) = resolve(configuration.logging)(ivy, md, default, configuration.artifactFilter)
|
val (report, err) =
|
||||||
|
resolve(configuration.logging)(ivy, md, default, configuration.artifactFilter)
|
||||||
err match {
|
err match {
|
||||||
case Some(x) if !configuration.missingOk =>
|
case Some(x) if !configuration.missingOk =>
|
||||||
Left(UnresolvedWarning(x, uwconfig))
|
Left(UnresolvedWarning(x, uwconfig))
|
||||||
case _ =>
|
case _ =>
|
||||||
val cachedDescriptor = ivy.getSettings.getResolutionCacheManager.getResolvedIvyFileInCache(md.getModuleRevisionId)
|
val cachedDescriptor = ivy.getSettings.getResolutionCacheManager
|
||||||
|
.getResolvedIvyFileInCache(md.getModuleRevisionId)
|
||||||
val uReport = IvyRetrieve.updateReport(report, cachedDescriptor)
|
val uReport = IvyRetrieve.updateReport(report, cachedDescriptor)
|
||||||
configuration.retrieve match {
|
configuration.retrieve match {
|
||||||
case Some(rConf) => Right(retrieve(log, ivy, uReport, rConf))
|
case Some(rConf) => Right(retrieve(log, ivy, uReport, rConf))
|
||||||
|
|
@ -185,11 +288,14 @@ object IvyActions {
|
||||||
}
|
}
|
||||||
@deprecated("No longer used.", "0.13.6")
|
@deprecated("No longer used.", "0.13.6")
|
||||||
def processUnresolved(err: ResolveException, log: Logger): Unit = ()
|
def processUnresolved(err: ResolveException, log: Logger): Unit = ()
|
||||||
def groupedConflicts[T](moduleFilter: ModuleFilter, grouping: ModuleID => T)(report: UpdateReport): Map[T, Set[String]] =
|
def groupedConflicts[T](moduleFilter: ModuleFilter, grouping: ModuleID => T)(
|
||||||
|
report: UpdateReport
|
||||||
|
): Map[T, Set[String]] =
|
||||||
report.configurations.flatMap { confReport =>
|
report.configurations.flatMap { confReport =>
|
||||||
val evicted = confReport.evicted.filter(moduleFilter)
|
val evicted = confReport.evicted.filter(moduleFilter)
|
||||||
val evictedSet = evicted.map(m => (m.organization, m.name)).toSet
|
val evictedSet = evicted.map(m => (m.organization, m.name)).toSet
|
||||||
val conflicted = confReport.allModules.filter(mod => evictedSet((mod.organization, mod.name)))
|
val conflicted =
|
||||||
|
confReport.allModules.filter(mod => evictedSet((mod.organization, mod.name)))
|
||||||
grouped(grouping)(conflicted ++ evicted)
|
grouped(grouping)(conflicted ++ evicted)
|
||||||
}.toMap
|
}.toMap
|
||||||
|
|
||||||
|
|
@ -197,27 +303,59 @@ object IvyActions {
|
||||||
mods groupBy (grouping) mapValues (_.map(_.revision).toSet)
|
mods groupBy (grouping) mapValues (_.map(_.revision).toSet)
|
||||||
|
|
||||||
@deprecated("This is no longer public.", "0.13.6")
|
@deprecated("This is no longer public.", "0.13.6")
|
||||||
def transitiveScratch(ivySbt: IvySbt, label: String, config: GetClassifiersConfiguration, log: Logger): UpdateReport =
|
def transitiveScratch(
|
||||||
transitiveScratch(ivySbt, label, config, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, log)
|
ivySbt: IvySbt,
|
||||||
|
label: String,
|
||||||
|
config: GetClassifiersConfiguration,
|
||||||
|
log: Logger
|
||||||
|
): UpdateReport =
|
||||||
|
transitiveScratch(
|
||||||
|
ivySbt,
|
||||||
|
label,
|
||||||
|
config,
|
||||||
|
UnresolvedWarningConfiguration(),
|
||||||
|
LogicalClock.unknown,
|
||||||
|
None,
|
||||||
|
log
|
||||||
|
)
|
||||||
|
|
||||||
private[sbt] def transitiveScratch(ivySbt: IvySbt, label: String, config: GetClassifiersConfiguration,
|
private[sbt] def transitiveScratch(
|
||||||
uwconfig: UnresolvedWarningConfiguration, logicalClock: LogicalClock, depDir: Option[File], log: Logger): UpdateReport =
|
ivySbt: IvySbt,
|
||||||
{
|
label: String,
|
||||||
import config.{ configuration => c, ivyScala, module => mod }
|
config: GetClassifiersConfiguration,
|
||||||
import mod.{ id, modules => deps }
|
uwconfig: UnresolvedWarningConfiguration,
|
||||||
val base = restrictedCopy(id, true).withName(id.name + "$" + label)
|
logicalClock: LogicalClock,
|
||||||
val module = new ivySbt.Module(InlineConfiguration(false, ivyScala, base, ModuleInfo(base.name), deps))
|
depDir: Option[File],
|
||||||
val report = updateEither(module, c, uwconfig, logicalClock, depDir, log) match {
|
log: Logger
|
||||||
case Right(r) => r
|
): UpdateReport = {
|
||||||
case Left(w) =>
|
import config.{ configuration => c, ivyScala, module => mod }
|
||||||
throw w.resolveException
|
import mod.{ id, modules => deps }
|
||||||
}
|
val base = restrictedCopy(id, true).withName(id.name + "$" + label)
|
||||||
val newConfig = config.copy(module = mod.copy(modules = report.allModules))
|
val module =
|
||||||
updateClassifiers(ivySbt, newConfig, uwconfig, logicalClock, depDir, Vector(), log)
|
new ivySbt.Module(InlineConfiguration(false, ivyScala, base, ModuleInfo(base.name), deps))
|
||||||
|
val report = updateEither(module, c, uwconfig, logicalClock, depDir, log) match {
|
||||||
|
case Right(r) => r
|
||||||
|
case Left(w) =>
|
||||||
|
throw w.resolveException
|
||||||
}
|
}
|
||||||
|
val newConfig = config.copy(module = mod.copy(modules = report.allModules))
|
||||||
|
updateClassifiers(ivySbt, newConfig, uwconfig, logicalClock, depDir, Vector(), log)
|
||||||
|
}
|
||||||
@deprecated("This is no longer public.", "0.13.6")
|
@deprecated("This is no longer public.", "0.13.6")
|
||||||
def updateClassifiers(ivySbt: IvySbt, config: GetClassifiersConfiguration, log: Logger): UpdateReport =
|
def updateClassifiers(
|
||||||
updateClassifiers(ivySbt, config, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, Vector(), log)
|
ivySbt: IvySbt,
|
||||||
|
config: GetClassifiersConfiguration,
|
||||||
|
log: Logger
|
||||||
|
): UpdateReport =
|
||||||
|
updateClassifiers(
|
||||||
|
ivySbt,
|
||||||
|
config,
|
||||||
|
UnresolvedWarningConfiguration(),
|
||||||
|
LogicalClock.unknown,
|
||||||
|
None,
|
||||||
|
Vector(),
|
||||||
|
log
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates explicit artifacts for each classifier in `config.module`, and then attempts to resolve them directly. This
|
* Creates explicit artifacts for each classifier in `config.module`, and then attempts to resolve them directly. This
|
||||||
|
|
@ -228,64 +366,83 @@ object IvyActions {
|
||||||
* @param config important to set `config.configuration.types` to only allow artifact types that can correspond to
|
* @param config important to set `config.configuration.types` to only allow artifact types that can correspond to
|
||||||
* "classified" artifacts (sources and javadocs).
|
* "classified" artifacts (sources and javadocs).
|
||||||
*/
|
*/
|
||||||
private[sbt] def updateClassifiers(ivySbt: IvySbt, config: GetClassifiersConfiguration,
|
private[sbt] def updateClassifiers(
|
||||||
uwconfig: UnresolvedWarningConfiguration, logicalClock: LogicalClock, depDir: Option[File],
|
ivySbt: IvySbt,
|
||||||
artifacts: Vector[(String, ModuleID, Artifact, File)],
|
config: GetClassifiersConfiguration,
|
||||||
log: Logger): UpdateReport =
|
uwconfig: UnresolvedWarningConfiguration,
|
||||||
{
|
logicalClock: LogicalClock,
|
||||||
import config.{ configuration => c, module => mod, _ }
|
depDir: Option[File],
|
||||||
import mod.{ configurations => confs, _ }
|
artifacts: Vector[(String, ModuleID, Artifact, File)],
|
||||||
assert(classifiers.nonEmpty, "classifiers cannot be empty")
|
log: Logger
|
||||||
assert(c.artifactFilter.types.nonEmpty, "UpdateConfiguration must filter on some types")
|
): UpdateReport = {
|
||||||
val baseModules = modules map { m => restrictedCopy(m, true) }
|
import config.{ configuration => c, module => mod, _ }
|
||||||
// Adding list of explicit artifacts here.
|
import mod.{ configurations => confs, _ }
|
||||||
val deps = baseModules.distinct flatMap classifiedArtifacts(classifiers, exclude, artifacts)
|
assert(classifiers.nonEmpty, "classifiers cannot be empty")
|
||||||
val base = restrictedCopy(id, true).withName(id.name + classifiers.mkString("$", "_", ""))
|
assert(c.artifactFilter.types.nonEmpty, "UpdateConfiguration must filter on some types")
|
||||||
val module = new ivySbt.Module(InlineConfiguration(false, ivyScala, base, ModuleInfo(base.name), deps).withConfigurations(confs))
|
val baseModules = modules map { m =>
|
||||||
// c.copy ensures c.types is preserved too
|
restrictedCopy(m, true)
|
||||||
val upConf = c.withMissingOk(true)
|
|
||||||
updateEither(module, upConf, uwconfig, logicalClock, depDir, log) match {
|
|
||||||
case Right(r) =>
|
|
||||||
// The artifacts that came from Ivy don't have their classifier set, let's set it according to
|
|
||||||
// FIXME: this is only done because IDE plugins depend on `classifier` to determine type. They
|
|
||||||
val typeClassifierMap: Map[String, String] =
|
|
||||||
((sourceArtifactTypes.toIterable map (_ -> Artifact.SourceClassifier))
|
|
||||||
:: (docArtifactTypes.toIterable map (_ -> Artifact.DocClassifier)) :: Nil).flatten.toMap
|
|
||||||
r.substitute { (conf, mid, artFileSeq) =>
|
|
||||||
artFileSeq map {
|
|
||||||
case (art, f) =>
|
|
||||||
// Deduce the classifier from the type if no classifier is present already
|
|
||||||
art.withClassifier(art.classifier orElse typeClassifierMap.get(art.`type`)) -> f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case Left(w) =>
|
|
||||||
throw w.resolveException
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Adding list of explicit artifacts here.
|
||||||
|
val deps = baseModules.distinct flatMap classifiedArtifacts(classifiers, exclude, artifacts)
|
||||||
|
val base = restrictedCopy(id, true).withName(id.name + classifiers.mkString("$", "_", ""))
|
||||||
|
val module = new ivySbt.Module(
|
||||||
|
InlineConfiguration(false, ivyScala, base, ModuleInfo(base.name), deps)
|
||||||
|
.withConfigurations(confs)
|
||||||
|
)
|
||||||
|
// c.copy ensures c.types is preserved too
|
||||||
|
val upConf = c.withMissingOk(true)
|
||||||
|
updateEither(module, upConf, uwconfig, logicalClock, depDir, log) match {
|
||||||
|
case Right(r) =>
|
||||||
|
// The artifacts that came from Ivy don't have their classifier set, let's set it according to
|
||||||
|
// FIXME: this is only done because IDE plugins depend on `classifier` to determine type. They
|
||||||
|
val typeClassifierMap: Map[String, String] =
|
||||||
|
((sourceArtifactTypes.toIterable map (_ -> Artifact.SourceClassifier))
|
||||||
|
:: (docArtifactTypes.toIterable map (_ -> Artifact.DocClassifier)) :: Nil).flatten.toMap
|
||||||
|
r.substitute { (conf, mid, artFileSeq) =>
|
||||||
|
artFileSeq map {
|
||||||
|
case (art, f) =>
|
||||||
|
// Deduce the classifier from the type if no classifier is present already
|
||||||
|
art.withClassifier(art.classifier orElse typeClassifierMap.get(art.`type`)) -> f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case Left(w) =>
|
||||||
|
throw w.resolveException
|
||||||
|
}
|
||||||
|
}
|
||||||
// This version adds explicit artifact
|
// This version adds explicit artifact
|
||||||
private[sbt] def classifiedArtifacts(
|
private[sbt] def classifiedArtifacts(
|
||||||
classifiers: Vector[String],
|
classifiers: Vector[String],
|
||||||
exclude: Map[ModuleID, Set[String]],
|
exclude: Map[ModuleID, Set[String]],
|
||||||
artifacts: Vector[(String, ModuleID, Artifact, File)]
|
artifacts: Vector[(String, ModuleID, Artifact, File)]
|
||||||
)(m: ModuleID): Option[ModuleID] = {
|
)(m: ModuleID): Option[ModuleID] = {
|
||||||
def sameModule(m1: ModuleID, m2: ModuleID): Boolean = m1.organization == m2.organization && m1.name == m2.name && m1.revision == m2.revision
|
def sameModule(m1: ModuleID, m2: ModuleID): Boolean =
|
||||||
def explicitArtifacts =
|
m1.organization == m2.organization && m1.name == m2.name && m1.revision == m2.revision
|
||||||
{
|
def explicitArtifacts = {
|
||||||
val arts = (artifacts collect { case (_, x, art, _) if sameModule(m, x) && art.classifier.isDefined => art }).distinct
|
val arts = (artifacts collect {
|
||||||
if (arts.isEmpty) None
|
case (_, x, art, _) if sameModule(m, x) && art.classifier.isDefined => art
|
||||||
else Some(intransitiveModuleWithExplicitArts(m, arts))
|
}).distinct
|
||||||
}
|
if (arts.isEmpty) None
|
||||||
|
else Some(intransitiveModuleWithExplicitArts(m, arts))
|
||||||
|
}
|
||||||
def hardcodedArtifacts = classifiedArtifacts(classifiers, exclude)(m)
|
def hardcodedArtifacts = classifiedArtifacts(classifiers, exclude)(m)
|
||||||
explicitArtifacts orElse hardcodedArtifacts
|
explicitArtifacts orElse hardcodedArtifacts
|
||||||
}
|
}
|
||||||
private def classifiedArtifacts(classifiers: Vector[String], exclude: Map[ModuleID, Set[String]])(m: ModuleID): Option[ModuleID] =
|
private def classifiedArtifacts(
|
||||||
{
|
classifiers: Vector[String],
|
||||||
val excluded = exclude getOrElse (restrictedCopy(m, false), Set.empty)
|
exclude: Map[ModuleID, Set[String]]
|
||||||
val included = classifiers filterNot excluded
|
)(m: ModuleID): Option[ModuleID] = {
|
||||||
if (included.isEmpty) None else {
|
val excluded = exclude getOrElse (restrictedCopy(m, false), Set.empty)
|
||||||
Some(intransitiveModuleWithExplicitArts(module = m, arts = classifiedArtifacts(m.name, included)))
|
val included = classifiers filterNot excluded
|
||||||
}
|
if (included.isEmpty) None
|
||||||
|
else {
|
||||||
|
Some(
|
||||||
|
intransitiveModuleWithExplicitArts(
|
||||||
|
module = m,
|
||||||
|
arts = classifiedArtifacts(m.name, included)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Explicitly set an "include all" rule (the default) because otherwise, if we declare ANY explicitArtifacts,
|
* Explicitly set an "include all" rule (the default) because otherwise, if we declare ANY explicitArtifacts,
|
||||||
|
|
@ -300,93 +457,170 @@ object IvyActions {
|
||||||
* }}}
|
* }}}
|
||||||
* `usage.getDependencyIncludesSet` returns null if there are no (explicit) include rules.
|
* `usage.getDependencyIncludesSet` returns null if there are no (explicit) include rules.
|
||||||
*/
|
*/
|
||||||
private def intransitiveModuleWithExplicitArts(module: ModuleID, arts: Vector[Artifact]): ModuleID =
|
private def intransitiveModuleWithExplicitArts(
|
||||||
module.withIsTransitive(false).withExplicitArtifacts(arts).withInclusions(Vector(InclExclRule.everything))
|
module: ModuleID,
|
||||||
|
arts: Vector[Artifact]
|
||||||
|
): ModuleID =
|
||||||
|
module
|
||||||
|
.withIsTransitive(false)
|
||||||
|
.withExplicitArtifacts(arts)
|
||||||
|
.withInclusions(Vector(InclExclRule.everything))
|
||||||
|
|
||||||
def addExcluded(report: UpdateReport, classifiers: Vector[String], exclude: Map[ModuleID, Set[String]]): UpdateReport =
|
def addExcluded(
|
||||||
report.addMissing { id => classifiedArtifacts(id.name, classifiers filter getExcluded(id, exclude)) }
|
report: UpdateReport,
|
||||||
|
classifiers: Vector[String],
|
||||||
|
exclude: Map[ModuleID, Set[String]]
|
||||||
|
): UpdateReport =
|
||||||
|
report.addMissing { id =>
|
||||||
|
classifiedArtifacts(id.name, classifiers filter getExcluded(id, exclude))
|
||||||
|
}
|
||||||
def classifiedArtifacts(name: String, classifiers: Vector[String]): Vector[Artifact] =
|
def classifiedArtifacts(name: String, classifiers: Vector[String]): Vector[Artifact] =
|
||||||
classifiers map { c => Artifact.classified(name, c) }
|
classifiers map { c =>
|
||||||
|
Artifact.classified(name, c)
|
||||||
|
}
|
||||||
private[this] def getExcluded(id: ModuleID, exclude: Map[ModuleID, Set[String]]): Set[String] =
|
private[this] def getExcluded(id: ModuleID, exclude: Map[ModuleID, Set[String]]): Set[String] =
|
||||||
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 { case (_, mod, art) => art.classifier.map { c => (restrictedCopy(mod, false), c) } } groupBy (_._1) map { case (mod, pairs) => (mod, pairs.map(_._2).toSet) }
|
report.allMissing flatMap {
|
||||||
|
case (_, mod, art) =>
|
||||||
|
art.classifier.map { c =>
|
||||||
|
(restrictedCopy(mod, false), c)
|
||||||
|
}
|
||||||
|
} groupBy (_._1) map { case (mod, pairs) => (mod, pairs.map(_._2).toSet) }
|
||||||
|
|
||||||
private[this] def restrictedCopy(m: ModuleID, confs: Boolean) =
|
private[this] def restrictedCopy(m: ModuleID, confs: Boolean) =
|
||||||
ModuleID(m.organization, m.name, m.revision).withCrossVersion(m.crossVersion).withExtraAttributes(m.extraAttributes).withConfigurations(if (confs) m.configurations else None)
|
ModuleID(m.organization, m.name, m.revision)
|
||||||
|
.withCrossVersion(m.crossVersion)
|
||||||
|
.withExtraAttributes(m.extraAttributes)
|
||||||
|
.withConfigurations(if (confs) m.configurations else None)
|
||||||
.branch(m.branchName)
|
.branch(m.branchName)
|
||||||
|
|
||||||
private[this] def resolve(logging: UpdateLogging)(ivy: Ivy, module: DefaultModuleDescriptor, defaultConf: String, filter: ArtifactTypeFilter): (ResolveReport, Option[ResolveException]) =
|
private[this] def resolve(logging: UpdateLogging)(
|
||||||
{
|
ivy: Ivy,
|
||||||
val resolveOptions = new ResolveOptions
|
module: DefaultModuleDescriptor,
|
||||||
val resolveId = ResolveOptions.getDefaultResolveId(module)
|
defaultConf: String,
|
||||||
resolveOptions.setResolveId(resolveId)
|
filter: ArtifactTypeFilter
|
||||||
resolveOptions.setArtifactFilter(filter)
|
): (ResolveReport, Option[ResolveException]) = {
|
||||||
resolveOptions.setLog(ivyLogLevel(logging))
|
val resolveOptions = new ResolveOptions
|
||||||
ResolutionCache.cleanModule(module.getModuleRevisionId, resolveId, ivy.getSettings.getResolutionCacheManager)
|
val resolveId = ResolveOptions.getDefaultResolveId(module)
|
||||||
val resolveReport = ivy.resolve(module, resolveOptions)
|
resolveOptions.setResolveId(resolveId)
|
||||||
val err =
|
resolveOptions.setArtifactFilter(filter)
|
||||||
if (resolveReport.hasError) {
|
resolveOptions.setLog(ivyLogLevel(logging))
|
||||||
val messages = resolveReport.getAllProblemMessages.toArray.map(_.toString).distinct
|
ResolutionCache.cleanModule(
|
||||||
val failedPaths = Map(resolveReport.getUnresolvedDependencies map { node =>
|
module.getModuleRevisionId,
|
||||||
val m = IvyRetrieve.toModuleID(node.getId)
|
resolveId,
|
||||||
val path = IvyRetrieve.findPath(node, module.getModuleRevisionId) map { x =>
|
ivy.getSettings.getResolutionCacheManager
|
||||||
IvyRetrieve.toModuleID(x.getId)
|
)
|
||||||
}
|
val resolveReport = ivy.resolve(module, resolveOptions)
|
||||||
m -> path
|
val err =
|
||||||
}: _*)
|
if (resolveReport.hasError) {
|
||||||
val failed = failedPaths.keys.toSeq
|
val messages = resolveReport.getAllProblemMessages.toArray.map(_.toString).distinct
|
||||||
Some(new ResolveException(messages, failed, failedPaths))
|
val failedPaths = Map(resolveReport.getUnresolvedDependencies map { node =>
|
||||||
} else None
|
val m = IvyRetrieve.toModuleID(node.getId)
|
||||||
(resolveReport, err)
|
val path = IvyRetrieve.findPath(node, module.getModuleRevisionId) map { x =>
|
||||||
|
IvyRetrieve.toModuleID(x.getId)
|
||||||
|
}
|
||||||
|
m -> path
|
||||||
|
}: _*)
|
||||||
|
val failed = failedPaths.keys.toSeq
|
||||||
|
Some(new ResolveException(messages, failed, failedPaths))
|
||||||
|
} else None
|
||||||
|
(resolveReport, err)
|
||||||
|
}
|
||||||
|
private def retrieve(
|
||||||
|
log: Logger,
|
||||||
|
ivy: Ivy,
|
||||||
|
report: UpdateReport,
|
||||||
|
config: RetrieveConfiguration
|
||||||
|
): UpdateReport =
|
||||||
|
retrieve(
|
||||||
|
log,
|
||||||
|
ivy,
|
||||||
|
report,
|
||||||
|
config.retrieveDirectory,
|
||||||
|
config.outputPattern,
|
||||||
|
config.sync,
|
||||||
|
config.configurationsToRetrieve
|
||||||
|
)
|
||||||
|
|
||||||
|
private def retrieve(
|
||||||
|
log: Logger,
|
||||||
|
ivy: Ivy,
|
||||||
|
report: UpdateReport,
|
||||||
|
base: File,
|
||||||
|
pattern: String,
|
||||||
|
sync: Boolean,
|
||||||
|
configurationsToRetrieve: Option[Set[Configuration]]
|
||||||
|
): UpdateReport = {
|
||||||
|
val configurationNames = configurationsToRetrieve match {
|
||||||
|
case None => None
|
||||||
|
case Some(configs) => Some(configs.map(_.name))
|
||||||
}
|
}
|
||||||
private def retrieve(log: Logger, ivy: Ivy, report: UpdateReport, config: RetrieveConfiguration): UpdateReport =
|
val existingFiles = PathFinder(base).allPaths.get filterNot { _.isDirectory }
|
||||||
retrieve(log, ivy, report, config.retrieveDirectory, config.outputPattern, config.sync, config.configurationsToRetrieve)
|
val toCopy = new collection.mutable.HashSet[(File, File)]
|
||||||
|
val retReport = report retrieve { (conf, mid, art, cached) =>
|
||||||
private def retrieve(log: Logger, ivy: Ivy, report: UpdateReport, base: File, pattern: String, sync: Boolean, configurationsToRetrieve: Option[Set[Configuration]]): UpdateReport =
|
configurationNames match {
|
||||||
{
|
case None => performRetrieve(conf, mid, art, base, pattern, cached, toCopy)
|
||||||
val configurationNames = configurationsToRetrieve match {
|
case Some(names) if names(conf) =>
|
||||||
case None => None
|
performRetrieve(conf, mid, art, base, pattern, cached, toCopy)
|
||||||
case Some(configs) => Some(configs.map(_.name))
|
case _ => cached
|
||||||
}
|
}
|
||||||
val existingFiles = PathFinder(base).allPaths.get filterNot { _.isDirectory }
|
}
|
||||||
val toCopy = new collection.mutable.HashSet[(File, File)]
|
IO.copy(toCopy)
|
||||||
val retReport = report retrieve { (conf, mid, art, cached) =>
|
val resolvedFiles = toCopy.map(_._2)
|
||||||
configurationNames match {
|
if (sync) {
|
||||||
case None => performRetrieve(conf, mid, art, base, pattern, cached, toCopy)
|
val filesToDelete = existingFiles.filterNot(resolvedFiles.contains)
|
||||||
case Some(names) if names(conf) => performRetrieve(conf, mid, art, base, pattern, cached, toCopy)
|
filesToDelete foreach { f =>
|
||||||
case _ => cached
|
log.info(s"Deleting old dependency: ${f.getAbsolutePath}")
|
||||||
}
|
f.delete()
|
||||||
}
|
}
|
||||||
IO.copy(toCopy)
|
|
||||||
val resolvedFiles = toCopy.map(_._2)
|
|
||||||
if (sync) {
|
|
||||||
val filesToDelete = existingFiles.filterNot(resolvedFiles.contains)
|
|
||||||
filesToDelete foreach { f =>
|
|
||||||
log.info(s"Deleting old dependency: ${f.getAbsolutePath}")
|
|
||||||
f.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
retReport
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private def performRetrieve(conf: String, mid: ModuleID, art: Artifact, base: File, pattern: String, cached: File, toCopy: collection.mutable.HashSet[(File, File)]): File = {
|
retReport
|
||||||
|
}
|
||||||
|
|
||||||
|
private def performRetrieve(
|
||||||
|
conf: String,
|
||||||
|
mid: ModuleID,
|
||||||
|
art: Artifact,
|
||||||
|
base: File,
|
||||||
|
pattern: String,
|
||||||
|
cached: File,
|
||||||
|
toCopy: collection.mutable.HashSet[(File, File)]
|
||||||
|
): File = {
|
||||||
val to = retrieveTarget(conf, mid, art, base, pattern)
|
val to = retrieveTarget(conf, mid, art, base, pattern)
|
||||||
toCopy += ((cached, to))
|
toCopy += ((cached, to))
|
||||||
to
|
to
|
||||||
}
|
}
|
||||||
|
|
||||||
private def retrieveTarget(conf: String, mid: ModuleID, art: Artifact, base: File, pattern: String): File =
|
private def retrieveTarget(
|
||||||
|
conf: String,
|
||||||
|
mid: ModuleID,
|
||||||
|
art: Artifact,
|
||||||
|
base: File,
|
||||||
|
pattern: String
|
||||||
|
): File =
|
||||||
new File(base, substitute(conf, mid, art, pattern))
|
new File(base, substitute(conf, mid, art, pattern))
|
||||||
|
|
||||||
private def substitute(conf: String, mid: ModuleID, art: Artifact, pattern: String): String =
|
private def substitute(conf: String, mid: ModuleID, art: Artifact, pattern: String): String = {
|
||||||
{
|
val mextra = IvySbt.javaMap(mid.extraAttributes, true)
|
||||||
val mextra = IvySbt.javaMap(mid.extraAttributes, true)
|
val aextra = IvySbt.extra(art, true)
|
||||||
val aextra = IvySbt.extra(art, true)
|
IvyPatternHelper.substitute(
|
||||||
IvyPatternHelper.substitute(pattern, mid.organization, mid.name, mid.branchName.orNull, mid.revision, art.name, art.`type`, art.extension, conf, null, mextra, aextra)
|
pattern,
|
||||||
}
|
mid.organization,
|
||||||
|
mid.name,
|
||||||
|
mid.branchName.orNull,
|
||||||
|
mid.revision,
|
||||||
|
art.name,
|
||||||
|
art.`type`,
|
||||||
|
art.extension,
|
||||||
|
conf,
|
||||||
|
null,
|
||||||
|
mextra,
|
||||||
|
aextra
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
import UpdateLogging.{ Quiet, Full, DownloadOnly, Default }
|
import UpdateLogging.{ Quiet, Full, DownloadOnly, Default }
|
||||||
import LogOptions.{ LOG_QUIET, LOG_DEFAULT, LOG_DOWNLOAD_ONLY }
|
import LogOptions.{ LOG_QUIET, LOG_DEFAULT, LOG_DOWNLOAD_ONLY }
|
||||||
|
|
@ -398,46 +632,57 @@ object IvyActions {
|
||||||
case Default => LOG_DOWNLOAD_ONLY
|
case Default => LOG_DOWNLOAD_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
def publish(module: ModuleDescriptor, artifacts: Seq[(IArtifact, File)], resolver: DependencyResolver, overwrite: Boolean): Unit =
|
def publish(
|
||||||
{
|
module: ModuleDescriptor,
|
||||||
if (artifacts.nonEmpty) {
|
artifacts: Seq[(IArtifact, File)],
|
||||||
checkFilesPresent(artifacts)
|
resolver: DependencyResolver,
|
||||||
try {
|
overwrite: Boolean
|
||||||
resolver.beginPublishTransaction(module.getModuleRevisionId(), overwrite);
|
): Unit = {
|
||||||
for ((artifact, file) <- artifacts)
|
if (artifacts.nonEmpty) {
|
||||||
resolver.publish(artifact, file, overwrite)
|
checkFilesPresent(artifacts)
|
||||||
resolver.commitPublishTransaction()
|
try {
|
||||||
} catch {
|
resolver.beginPublishTransaction(module.getModuleRevisionId(), overwrite);
|
||||||
case e: Throwable =>
|
for ((artifact, file) <- artifacts)
|
||||||
try { resolver.abortPublishTransaction() }
|
resolver.publish(artifact, file, overwrite)
|
||||||
finally { throw e }
|
resolver.commitPublishTransaction()
|
||||||
}
|
} catch {
|
||||||
|
case e: Throwable =>
|
||||||
|
try { resolver.abortPublishTransaction() } finally { throw e }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private[this] def checkFilesPresent(artifacts: Seq[(IArtifact, File)]): Unit = {
|
private[this] def checkFilesPresent(artifacts: Seq[(IArtifact, File)]): Unit = {
|
||||||
val missing = artifacts filter { case (a, file) => !file.exists }
|
val missing = artifacts filter { case (a, file) => !file.exists }
|
||||||
if (missing.nonEmpty)
|
if (missing.nonEmpty)
|
||||||
sys.error("Missing files for publishing:\n\t" + missing.map(_._2.getAbsolutePath).mkString("\n\t"))
|
sys.error(
|
||||||
|
"Missing files for publishing:\n\t" + missing.map(_._2.getAbsolutePath).mkString("\n\t")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final class ResolveException(
|
final class ResolveException(
|
||||||
val messages: Seq[String],
|
val messages: Seq[String],
|
||||||
val failed: Seq[ModuleID],
|
val failed: Seq[ModuleID],
|
||||||
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 => m -> Nil }: _*))
|
this(messages, failed, Map(failed map { m =>
|
||||||
|
m -> Nil
|
||||||
|
}: _*))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents unresolved dependency warning, which displays reconstructed dependency tree
|
* Represents unresolved dependency warning, which displays reconstructed dependency tree
|
||||||
* along with source position of each node.
|
* along with source position of each node.
|
||||||
*/
|
*/
|
||||||
final class UnresolvedWarning private[sbt] (
|
final class UnresolvedWarning private[sbt] (
|
||||||
val resolveException: ResolveException,
|
val resolveException: ResolveException,
|
||||||
val failedPaths: Seq[Seq[(ModuleID, Option[SourcePosition])]]
|
val failedPaths: Seq[Seq[(ModuleID, Option[SourcePosition])]]
|
||||||
)
|
)
|
||||||
object UnresolvedWarning {
|
object UnresolvedWarning {
|
||||||
private[sbt] def apply(err: ResolveException, config: UnresolvedWarningConfiguration): UnresolvedWarning = {
|
private[sbt] def apply(
|
||||||
|
err: ResolveException,
|
||||||
|
config: UnresolvedWarningConfiguration
|
||||||
|
): UnresolvedWarning = {
|
||||||
def modulePosition(m0: ModuleID): Option[SourcePosition] =
|
def modulePosition(m0: ModuleID): Option[SourcePosition] =
|
||||||
config.modulePositions.find {
|
config.modulePositions.find {
|
||||||
case (m, p) =>
|
case (m, p) =>
|
||||||
|
|
@ -454,20 +699,25 @@ object UnresolvedWarning {
|
||||||
}
|
}
|
||||||
apply(err, failedPaths)
|
apply(err, failedPaths)
|
||||||
}
|
}
|
||||||
private[sbt] def apply(err: ResolveException, failedPaths: Seq[Seq[(ModuleID, Option[SourcePosition])]]): UnresolvedWarning =
|
private[sbt] def apply(
|
||||||
|
err: ResolveException,
|
||||||
|
failedPaths: Seq[Seq[(ModuleID, Option[SourcePosition])]]
|
||||||
|
): UnresolvedWarning =
|
||||||
new UnresolvedWarning(err, failedPaths)
|
new UnresolvedWarning(err, failedPaths)
|
||||||
private[sbt] def sourcePosStr(posOpt: Option[SourcePosition]): String =
|
private[sbt] def sourcePosStr(posOpt: Option[SourcePosition]): String =
|
||||||
posOpt match {
|
posOpt match {
|
||||||
case Some(LinePosition(path, start)) => s" ($path#L$start)"
|
case Some(LinePosition(path, start)) => s" ($path#L$start)"
|
||||||
case Some(RangePosition(path, LineRange(start, end))) => s" ($path#L$start-$end)"
|
case Some(RangePosition(path, LineRange(start, end))) => s" ($path#L$start-$end)"
|
||||||
case _ => ""
|
case _ => ""
|
||||||
}
|
}
|
||||||
implicit val unresolvedWarningLines: ShowLines[UnresolvedWarning] = ShowLines { a =>
|
implicit val unresolvedWarningLines: ShowLines[UnresolvedWarning] = ShowLines { a =>
|
||||||
val withExtra = a.resolveException.failed.filter(_.extraDependencyAttributes.nonEmpty)
|
val withExtra = a.resolveException.failed.filter(_.extraDependencyAttributes.nonEmpty)
|
||||||
val buffer = mutable.ListBuffer[String]()
|
val buffer = mutable.ListBuffer[String]()
|
||||||
if (withExtra.nonEmpty) {
|
if (withExtra.nonEmpty) {
|
||||||
buffer += "\n\tNote: Some unresolved dependencies have extra attributes. Check that these dependencies exist with the requested attributes."
|
buffer += "\n\tNote: Some unresolved dependencies have extra attributes. Check that these dependencies exist with the requested attributes."
|
||||||
withExtra foreach { id => buffer += "\t\t" + id }
|
withExtra foreach { id =>
|
||||||
|
buffer += "\t\t" + id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (a.failedPaths.nonEmpty) {
|
if (a.failedPaths.nonEmpty) {
|
||||||
buffer += "\n\tNote: Unresolved dependencies path:"
|
buffer += "\n\tNote: Unresolved dependencies path:"
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,11 @@ package sbt.internal.librarymanagement
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
import org.apache.ivy.core.cache.{ ArtifactOrigin, CacheDownloadOptions, DefaultRepositoryCacheManager }
|
import org.apache.ivy.core.cache.{
|
||||||
|
ArtifactOrigin,
|
||||||
|
CacheDownloadOptions,
|
||||||
|
DefaultRepositoryCacheManager
|
||||||
|
}
|
||||||
import org.apache.ivy.core.module.descriptor.{ Artifact => IvyArtifact, DefaultArtifact }
|
import org.apache.ivy.core.module.descriptor.{ Artifact => IvyArtifact, DefaultArtifact }
|
||||||
import org.apache.ivy.plugins.repository.file.{ FileRepository => IvyFileRepository, FileResource }
|
import org.apache.ivy.plugins.repository.file.{ FileRepository => IvyFileRepository, FileResource }
|
||||||
import org.apache.ivy.plugins.repository.{ ArtifactResourceResolver, Resource, ResourceDownloader }
|
import org.apache.ivy.plugins.repository.{ ArtifactResourceResolver, Resource, ResourceDownloader }
|
||||||
|
|
@ -20,36 +24,46 @@ import scala.collection.mutable
|
||||||
import jawn.{ SupportParser, MutableFacade }
|
import jawn.{ SupportParser, MutableFacade }
|
||||||
|
|
||||||
class NotInCache(val id: ModuleID, cause: Throwable)
|
class NotInCache(val id: ModuleID, cause: Throwable)
|
||||||
extends RuntimeException(NotInCache(id, cause), cause) {
|
extends RuntimeException(NotInCache(id, cause), cause) {
|
||||||
def this(id: ModuleID) = this(id, null)
|
def this(id: ModuleID) = this(id, null)
|
||||||
}
|
}
|
||||||
private object NotInCache {
|
private object NotInCache {
|
||||||
def apply(id: ModuleID, cause: Throwable) =
|
def apply(id: ModuleID, cause: Throwable) = {
|
||||||
{
|
val postfix = if (cause == null) "" else (": " + cause.toString)
|
||||||
val postfix = if (cause == null) "" else (": " + cause.toString)
|
"File for " + id + " not in cache" + postfix
|
||||||
"File for " + id + " not in cache" + postfix
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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(moduleID: ModuleID, file: File, lock: Option[xsbti.GlobalLock], log: Logger): Unit = {
|
def cacheJar(moduleID: ModuleID, file: File, lock: Option[xsbti.GlobalLock], log: Logger): Unit = {
|
||||||
val artifact = defaultArtifact(moduleID)
|
val artifact = defaultArtifact(moduleID)
|
||||||
val resolved = new ResolvedResource(new FileResource(new IvyFileRepository, file), moduleID.revision)
|
val resolved =
|
||||||
|
new ResolvedResource(new FileResource(new IvyFileRepository, file), moduleID.revision)
|
||||||
withDefaultCache(lock, log) { cache =>
|
withDefaultCache(lock, log) { cache =>
|
||||||
val resolver = new ArtifactResourceResolver { def resolve(artifact: IvyArtifact) = resolved }
|
val resolver = new ArtifactResourceResolver { def resolve(artifact: IvyArtifact) = resolved }
|
||||||
cache.download(artifact, resolver, new FileDownloader, new CacheDownloadOptions)
|
cache.download(artifact, resolver, new FileDownloader, new CacheDownloadOptions)
|
||||||
()
|
()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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 { withCachedJar(id, lock, log)(_.delete); () }
|
try { withCachedJar(id, lock, log)(_.delete); () } catch {
|
||||||
catch { case e: Exception => log.debug("Error cleaning cached jar: " + e.toString) }
|
case e: Exception => log.debug("Error cleaning cached jar: " + e.toString)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Copies the cached jar for the given ID to the directory 'toDirectory'. If the jar is not in the cache, NotInCache is thrown.*/
|
/** Copies the cached jar for the given ID to the directory 'toDirectory'. If the jar is not in the cache, NotInCache is thrown.*/
|
||||||
def retrieveCachedJar(id: ModuleID, toDirectory: File, lock: Option[xsbti.GlobalLock], log: Logger) =
|
def retrieveCachedJar(
|
||||||
|
id: ModuleID,
|
||||||
|
toDirectory: File,
|
||||||
|
lock: Option[xsbti.GlobalLock],
|
||||||
|
log: Logger
|
||||||
|
) =
|
||||||
withCachedJar(id, lock, log) { cachedFile =>
|
withCachedJar(id, lock, log) { cachedFile =>
|
||||||
val copyTo = new File(toDirectory, cachedFile.getName)
|
val copyTo = new File(toDirectory, cachedFile.getName)
|
||||||
FileUtil.copy(cachedFile, copyTo, null)
|
FileUtil.copy(cachedFile, copyTo, null)
|
||||||
|
|
@ -57,41 +71,58 @@ class IvyCache(val ivyHome: Option[File]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the location of the cached jar for the given ID in the Ivy cache. If the jar is not in the cache, NotInCache is thrown .*/
|
/** Get the location of the cached jar for the given ID in the Ivy cache. If the jar is not in the cache, NotInCache is thrown .*/
|
||||||
def withCachedJar[T](id: ModuleID, lock: Option[xsbti.GlobalLock], log: Logger)(f: File => T): T =
|
def withCachedJar[T](id: ModuleID, lock: Option[xsbti.GlobalLock], log: Logger)(
|
||||||
{
|
f: File => T
|
||||||
val cachedFile =
|
): T = {
|
||||||
try {
|
val cachedFile =
|
||||||
withDefaultCache(lock, log) { cache =>
|
try {
|
||||||
val artifact = defaultArtifact(id)
|
withDefaultCache(lock, log) { cache =>
|
||||||
cache.getArchiveFileInCache(artifact, unknownOrigin(artifact))
|
val artifact = defaultArtifact(id)
|
||||||
}
|
cache.getArchiveFileInCache(artifact, unknownOrigin(artifact))
|
||||||
} catch { case e: Exception => throw new NotInCache(id, e) }
|
}
|
||||||
|
} catch { case e: Exception => throw new NotInCache(id, e) }
|
||||||
|
|
||||||
|
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)(f: DefaultRepositoryCacheManager => T): T =
|
def withDefaultCache[T](lock: Option[xsbti.GlobalLock], log: Logger)(
|
||||||
{
|
f: DefaultRepositoryCacheManager => T
|
||||||
val (ivy, _) = basicLocalIvy(lock, log)
|
): T = {
|
||||||
ivy.withIvy(log) { ivy =>
|
val (ivy, _) = basicLocalIvy(lock, log)
|
||||||
val cache = ivy.getSettings.getDefaultRepositoryCacheManager.asInstanceOf[DefaultRepositoryCacheManager]
|
ivy.withIvy(log) { ivy =>
|
||||||
cache.setUseOrigin(false)
|
val cache = ivy.getSettings.getDefaultRepositoryCacheManager
|
||||||
f(cache)
|
.asInstanceOf[DefaultRepositoryCacheManager]
|
||||||
}
|
cache.setUseOrigin(false)
|
||||||
|
f(cache)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
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)
|
val conf = new InlineIvyConfiguration(
|
||||||
val conf = new InlineIvyConfiguration(paths, Vector(local), Vector.empty, Vector.empty, false, lock, IvySbt.DefaultChecksums, None, UpdateOptions(), log)
|
paths,
|
||||||
(new IvySbt(conf), local)
|
Vector(local),
|
||||||
}
|
Vector.empty,
|
||||||
|
Vector.empty,
|
||||||
|
false,
|
||||||
|
lock,
|
||||||
|
IvySbt.DefaultChecksums,
|
||||||
|
None,
|
||||||
|
UpdateOptions(),
|
||||||
|
log
|
||||||
|
)
|
||||||
|
(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 = {
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,15 @@ package sbt.internal.librarymanagement
|
||||||
import sbt.librarymanagement._
|
import sbt.librarymanagement._
|
||||||
|
|
||||||
abstract class InlineConfigurationFunctions {
|
abstract class InlineConfigurationFunctions {
|
||||||
def configurations(explicitConfigurations: Iterable[Configuration], defaultConfiguration: Option[Configuration]) =
|
def configurations(
|
||||||
|
explicitConfigurations: Iterable[Configuration],
|
||||||
|
defaultConfiguration: Option[Configuration]
|
||||||
|
) =
|
||||||
if (explicitConfigurations.isEmpty) {
|
if (explicitConfigurations.isEmpty) {
|
||||||
defaultConfiguration match {
|
defaultConfiguration match {
|
||||||
case Some(Configurations.DefaultIvyConfiguration) => Configurations.Default :: Nil
|
case Some(Configurations.DefaultIvyConfiguration) => Configurations.Default :: Nil
|
||||||
case Some(Configurations.DefaultMavenConfiguration) => Configurations.defaultMavenConfigurations
|
case Some(Configurations.DefaultMavenConfiguration) =>
|
||||||
|
Configurations.defaultMavenConfigurations
|
||||||
case _ => Nil
|
case _ => Nil
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ private final class IvyLoggerInterface(logger: Logger) extends MessageLogger {
|
||||||
def setShowProgress(progress: Boolean): Unit = ()
|
def setShowProgress(progress: Boolean): Unit = ()
|
||||||
}
|
}
|
||||||
private final class SbtMessageLoggerEngine extends MessageLoggerEngine {
|
private final class SbtMessageLoggerEngine extends MessageLoggerEngine {
|
||||||
|
|
||||||
/** This is a hack to filter error messages about 'unknown resolver ...'. */
|
/** This is a hack to filter error messages about 'unknown resolver ...'. */
|
||||||
override def error(msg: String): Unit = if (SbtIvyLogger.acceptError(msg)) super.error(msg)
|
override def error(msg: String): Unit = if (SbtIvyLogger.acceptError(msg)) super.error(msg)
|
||||||
override def sumupProblems(): Unit = clearProblems()
|
override def sumupProblems(): Unit = clearProblems()
|
||||||
|
|
|
||||||
|
|
@ -21,39 +21,48 @@ object IvyRetrieve {
|
||||||
|
|
||||||
def moduleReports(confReport: ConfigurationResolveReport): Vector[ModuleReport] =
|
def moduleReports(confReport: ConfigurationResolveReport): Vector[ModuleReport] =
|
||||||
for {
|
for {
|
||||||
revId <- confReport.getModuleRevisionIds.toArray.toVector collect { case revId: ModuleRevisionId => revId }
|
revId <- confReport.getModuleRevisionIds.toArray.toVector collect {
|
||||||
|
case revId: ModuleRevisionId => revId
|
||||||
|
}
|
||||||
} yield moduleRevisionDetail(confReport, confReport.getDependency(revId))
|
} yield moduleRevisionDetail(confReport, confReport.getDependency(revId))
|
||||||
|
|
||||||
@deprecated("Internal only. No longer in use.", "0.13.6")
|
@deprecated("Internal only. No longer in use.", "0.13.6")
|
||||||
def artifactReports(mid: ModuleID, artReport: Seq[ArtifactDownloadReport]): ModuleReport =
|
def artifactReports(mid: ModuleID, artReport: Seq[ArtifactDownloadReport]): ModuleReport = {
|
||||||
{
|
val (resolved, missing) = artifacts(mid, artReport)
|
||||||
val (resolved, missing) = artifacts(mid, artReport)
|
ModuleReport(mid, resolved, missing)
|
||||||
ModuleReport(mid, resolved, missing)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private[sbt] def artifacts(mid: ModuleID, artReport: Seq[ArtifactDownloadReport]): (Vector[(Artifact, File)], Vector[Artifact]) =
|
private[sbt] def artifacts(
|
||||||
{
|
mid: ModuleID,
|
||||||
val missing = new mutable.ListBuffer[Artifact]
|
artReport: Seq[ArtifactDownloadReport]
|
||||||
val resolved = new mutable.ListBuffer[(Artifact, File)]
|
): (Vector[(Artifact, File)], Vector[Artifact]) = {
|
||||||
for (r <- artReport) {
|
val missing = new mutable.ListBuffer[Artifact]
|
||||||
val fileOpt = Option(r.getLocalFile)
|
val resolved = new mutable.ListBuffer[(Artifact, File)]
|
||||||
val art = toArtifact(r.getArtifact)
|
for (r <- artReport) {
|
||||||
fileOpt match {
|
val fileOpt = Option(r.getLocalFile)
|
||||||
case Some(file) => resolved += ((art, file))
|
val art = toArtifact(r.getArtifact)
|
||||||
case None => missing += art
|
fileOpt match {
|
||||||
}
|
case Some(file) => resolved += ((art, file))
|
||||||
|
case None => missing += art
|
||||||
}
|
}
|
||||||
(resolved.toVector, missing.toVector)
|
|
||||||
}
|
}
|
||||||
|
(resolved.toVector, missing.toVector)
|
||||||
|
}
|
||||||
|
|
||||||
// We need this because current module report used as part of UpdateReport/ConfigurationReport contains
|
// We need this because current module report used as part of UpdateReport/ConfigurationReport contains
|
||||||
// only the revolved modules.
|
// only the revolved modules.
|
||||||
// Sometimes the entire module can be excluded via rules etc.
|
// Sometimes the entire module can be excluded via rules etc.
|
||||||
private[sbt] def organizationArtifactReports(confReport: ConfigurationResolveReport): Vector[OrganizationArtifactReport] = {
|
private[sbt] def organizationArtifactReports(
|
||||||
val moduleIds = confReport.getModuleIds.toArray.toVector collect { case mId: IvyModuleId => mId }
|
confReport: ConfigurationResolveReport
|
||||||
|
): Vector[OrganizationArtifactReport] = {
|
||||||
|
val moduleIds = confReport.getModuleIds.toArray.toVector collect {
|
||||||
|
case mId: IvyModuleId => 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 { moduleRevisionDetail(confReport, _) })
|
OrganizationArtifactReport(mid.getOrganisation, mid.getName, deps map {
|
||||||
|
moduleRevisionDetail(confReport, _)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
moduleIds map { organizationArtifact }
|
moduleIds map { organizationArtifact }
|
||||||
}
|
}
|
||||||
|
|
@ -65,10 +74,16 @@ object IvyRetrieve {
|
||||||
case x => Some(x.trim)
|
case x => Some(x.trim)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def moduleRevisionDetail(confReport: ConfigurationResolveReport, dep: IvyNode): ModuleReport = {
|
private[sbt] def moduleRevisionDetail(
|
||||||
|
confReport: ConfigurationResolveReport,
|
||||||
|
dep: IvyNode
|
||||||
|
): ModuleReport = {
|
||||||
def toExtraAttributes(ea: ju.Map[_, _]): Map[String, String] =
|
def toExtraAttributes(ea: ju.Map[_, _]): Map[String, String] =
|
||||||
Map(ea.entrySet.toArray collect {
|
Map(ea.entrySet.toArray collect {
|
||||||
case entry: ju.Map.Entry[_, _] if nonEmptyString(entry.getKey.toString).isDefined && nonEmptyString(entry.getValue.toString).isDefined =>
|
case entry: ju.Map.Entry[_, _]
|
||||||
|
if nonEmptyString(entry.getKey.toString).isDefined && nonEmptyString(
|
||||||
|
entry.getValue.toString
|
||||||
|
).isDefined =>
|
||||||
(entry.getKey.toString, entry.getValue.toString)
|
(entry.getKey.toString, entry.getValue.toString)
|
||||||
}: _*)
|
}: _*)
|
||||||
def toCaller(caller: IvyCaller): Caller = {
|
def toCaller(caller: IvyCaller): Caller = {
|
||||||
|
|
@ -80,11 +95,32 @@ object IvyRetrieve {
|
||||||
val (extraAttributes, isForce, isChanging, isTransitive, isDirectlyForce) = ddOpt match {
|
val (extraAttributes, isForce, isChanging, isTransitive, isDirectlyForce) = ddOpt match {
|
||||||
case Some(dd: SbtDefaultDependencyDescriptor) =>
|
case Some(dd: SbtDefaultDependencyDescriptor) =>
|
||||||
val mod = dd.dependencyModuleId
|
val mod = dd.dependencyModuleId
|
||||||
(toExtraAttributes(dd.getExtraAttributes), mod.isForce, mod.isChanging, mod.isTransitive, mod.isForce)
|
(
|
||||||
case Some(dd) => (toExtraAttributes(dd.getExtraAttributes), dd.isForce, dd.isChanging, dd.isTransitive, false)
|
toExtraAttributes(dd.getExtraAttributes),
|
||||||
case None => (Map.empty[String, String], false, false, true, false)
|
mod.isForce,
|
||||||
|
mod.isChanging,
|
||||||
|
mod.isTransitive,
|
||||||
|
mod.isForce
|
||||||
|
)
|
||||||
|
case Some(dd) =>
|
||||||
|
(
|
||||||
|
toExtraAttributes(dd.getExtraAttributes),
|
||||||
|
dd.isForce,
|
||||||
|
dd.isChanging,
|
||||||
|
dd.isTransitive,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
case None => (Map.empty[String, String], false, false, true, false)
|
||||||
}
|
}
|
||||||
Caller(m, callerConfigurations, extraAttributes, isForce, isChanging, isTransitive, isDirectlyForce)
|
Caller(
|
||||||
|
m,
|
||||||
|
callerConfigurations,
|
||||||
|
extraAttributes,
|
||||||
|
isForce,
|
||||||
|
isChanging,
|
||||||
|
isTransitive,
|
||||||
|
isDirectlyForce
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val revId = dep.getResolvedId
|
val revId = dep.getResolvedId
|
||||||
val moduleId = toModuleID(revId)
|
val moduleId = toModuleID(revId)
|
||||||
|
|
@ -106,9 +142,9 @@ 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,
|
(true, nonEmptyString(Option(ed.getConflictManager) map { _.toString } getOrElse {
|
||||||
nonEmptyString(Option(ed.getConflictManager) map { _.toString } getOrElse { "transitive" }),
|
"transitive"
|
||||||
nonEmptyString(ed.getDetail))
|
}), nonEmptyString(ed.getDetail))
|
||||||
case None => (true, None, None)
|
case None => (true, None, None)
|
||||||
}
|
}
|
||||||
case _ => (false, None, None)
|
case _ => (false, None, None)
|
||||||
|
|
@ -133,40 +169,74 @@ object IvyRetrieve {
|
||||||
val isDefault = Option(dep.getDescriptor) map { _.isDefault }
|
val isDefault = Option(dep.getDescriptor) map { _.isDefault }
|
||||||
val configurations = dep.getConfigurations(confReport.getConfiguration).toVector
|
val configurations = dep.getConfigurations(confReport.getConfiguration).toVector
|
||||||
val licenses: Vector[(String, Option[String])] = mdOpt match {
|
val licenses: Vector[(String, Option[String])] = mdOpt match {
|
||||||
case Some(md) => md.getLicenses.toVector collect {
|
case Some(md) =>
|
||||||
case lic: IvyLicense if Option(lic.getName).isDefined =>
|
md.getLicenses.toVector collect {
|
||||||
val temporaryURL = "http://localhost"
|
case lic: IvyLicense if Option(lic.getName).isDefined =>
|
||||||
(lic.getName, nonEmptyString(lic.getUrl) orElse { Some(temporaryURL) })
|
val temporaryURL = "http://localhost"
|
||||||
}
|
(lic.getName, nonEmptyString(lic.getUrl) orElse { Some(temporaryURL) })
|
||||||
|
}
|
||||||
case _ => Vector.empty
|
case _ => Vector.empty
|
||||||
}
|
}
|
||||||
val callers = dep.getCallers(confReport.getConfiguration).toVector map { toCaller }
|
val callers = dep.getCallers(confReport.getConfiguration).toVector map { toCaller }
|
||||||
val (resolved, missing) = artifacts(moduleId, confReport getDownloadReports revId)
|
val (resolved, missing) = artifacts(moduleId, confReport getDownloadReports revId)
|
||||||
|
|
||||||
ModuleReport(moduleId, resolved, missing, status, publicationDate, resolver, artifactResolver,
|
ModuleReport(
|
||||||
evicted, evictedData, evictedReason, problem, homepage, extraAttributes, isDefault, branch,
|
moduleId,
|
||||||
configurations, licenses, callers)
|
resolved,
|
||||||
|
missing,
|
||||||
|
status,
|
||||||
|
publicationDate,
|
||||||
|
resolver,
|
||||||
|
artifactResolver,
|
||||||
|
evicted,
|
||||||
|
evictedData,
|
||||||
|
evictedReason,
|
||||||
|
problem,
|
||||||
|
homepage,
|
||||||
|
extraAttributes,
|
||||||
|
isDefault,
|
||||||
|
branch,
|
||||||
|
configurations,
|
||||||
|
licenses,
|
||||||
|
callers
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
def evicted(confReport: ConfigurationResolveReport): Seq[ModuleID] =
|
def evicted(confReport: ConfigurationResolveReport): Seq[ModuleID] =
|
||||||
confReport.getEvictedNodes.map(node => toModuleID(node.getId))
|
confReport.getEvictedNodes.map(node => toModuleID(node.getId))
|
||||||
|
|
||||||
def toModuleID(revID: ModuleRevisionId): ModuleID =
|
def toModuleID(revID: ModuleRevisionId): ModuleID =
|
||||||
ModuleID(revID.getOrganisation, revID.getName, revID.getRevision).withExtraAttributes(IvySbt.getExtraAttributes(revID))
|
ModuleID(revID.getOrganisation, revID.getName, revID.getRevision)
|
||||||
|
.withExtraAttributes(IvySbt.getExtraAttributes(revID))
|
||||||
.branch(nonEmptyString(revID.getBranch))
|
.branch(nonEmptyString(revID.getBranch))
|
||||||
|
|
||||||
def toArtifact(art: IvyArtifact): Artifact =
|
def toArtifact(art: IvyArtifact): Artifact = {
|
||||||
{
|
import art._
|
||||||
import art._
|
Artifact(
|
||||||
Artifact(getName, getType, getExt, Option(getExtraAttribute("classifier")), getConfigurations.toVector map Configurations.config, Option(getUrl))
|
getName,
|
||||||
}
|
getType,
|
||||||
|
getExt,
|
||||||
|
Option(getExtraAttribute("classifier")),
|
||||||
|
getConfigurations.toVector map Configurations.config,
|
||||||
|
Option(getUrl)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
def updateReport(report: ResolveReport, cachedDescriptor: File): UpdateReport =
|
def updateReport(report: ResolveReport, cachedDescriptor: File): UpdateReport =
|
||||||
UpdateReport(cachedDescriptor, reports(report) map configurationReport, updateStats(report), Map.empty) recomputeStamps ()
|
UpdateReport(
|
||||||
|
cachedDescriptor,
|
||||||
|
reports(report) map configurationReport,
|
||||||
|
updateStats(report),
|
||||||
|
Map.empty
|
||||||
|
) recomputeStamps ()
|
||||||
def updateStats(report: ResolveReport): UpdateStats =
|
def updateStats(report: ResolveReport): UpdateStats =
|
||||||
UpdateStats(report.getResolveTime, report.getDownloadTime, report.getDownloadSize, false)
|
UpdateStats(report.getResolveTime, report.getDownloadTime, report.getDownloadSize, false)
|
||||||
def configurationReport(confReport: ConfigurationResolveReport): ConfigurationReport =
|
def configurationReport(confReport: ConfigurationResolveReport): ConfigurationReport =
|
||||||
ConfigurationReport(confReport.getConfiguration, moduleReports(confReport), organizationArtifactReports(confReport))
|
ConfigurationReport(
|
||||||
|
confReport.getConfiguration,
|
||||||
|
moduleReports(confReport),
|
||||||
|
organizationArtifactReports(confReport)
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to find Ivy graph path the from node to target.
|
* Tries to find Ivy graph path the from node to target.
|
||||||
|
|
|
||||||
|
|
@ -11,36 +11,59 @@ private[sbt] object JsonUtil {
|
||||||
def sbtOrgTemp = "org.scala-sbt.temp"
|
def sbtOrgTemp = "org.scala-sbt.temp"
|
||||||
def fakeCallerOrganization = "org.scala-sbt.temp-callers"
|
def fakeCallerOrganization = "org.scala-sbt.temp-callers"
|
||||||
|
|
||||||
def parseUpdateReport(md: ModuleDescriptor, path: File, cachedDescriptor: File, log: Logger): UpdateReport =
|
def parseUpdateReport(
|
||||||
{
|
md: ModuleDescriptor,
|
||||||
try {
|
path: File,
|
||||||
val lite = CacheStore(path).read[UpdateReportLite]
|
cachedDescriptor: File,
|
||||||
fromLite(lite, cachedDescriptor)
|
log: Logger
|
||||||
} catch {
|
): UpdateReport = {
|
||||||
case e: Throwable =>
|
try {
|
||||||
log.error("Unable to parse mini graph: " + path.toString)
|
val lite = CacheStore(path).read[UpdateReportLite]
|
||||||
throw e
|
fromLite(lite, cachedDescriptor)
|
||||||
}
|
} catch {
|
||||||
}
|
case e: Throwable =>
|
||||||
def writeUpdateReport(ur: UpdateReport, graphPath: File): Unit =
|
log.error("Unable to parse mini graph: " + path.toString)
|
||||||
{
|
throw e
|
||||||
sbt.io.IO.createDirectory(graphPath.getParentFile)
|
|
||||||
CacheStore(graphPath).write(toLite(ur))
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
def writeUpdateReport(ur: UpdateReport, graphPath: File): Unit = {
|
||||||
|
sbt.io.IO.createDirectory(graphPath.getParentFile)
|
||||||
|
CacheStore(graphPath).write(toLite(ur))
|
||||||
|
}
|
||||||
def toLite(ur: UpdateReport): UpdateReportLite =
|
def toLite(ur: UpdateReport): UpdateReportLite =
|
||||||
UpdateReportLite(ur.configurations map { cr =>
|
UpdateReportLite(ur.configurations map { cr =>
|
||||||
ConfigurationReportLite(cr.configuration, cr.details map { oar =>
|
ConfigurationReportLite(
|
||||||
OrganizationArtifactReport(oar.organization, oar.name, oar.modules map { mr =>
|
cr.configuration,
|
||||||
ModuleReport(
|
cr.details map {
|
||||||
mr.module, mr.artifacts, mr.missingArtifacts, mr.status,
|
oar =>
|
||||||
mr.publicationDate, mr.resolver, mr.artifactResolver,
|
OrganizationArtifactReport(
|
||||||
mr.evicted, mr.evictedData, mr.evictedReason,
|
oar.organization,
|
||||||
mr.problem, mr.homepage, mr.extraAttributes,
|
oar.name,
|
||||||
mr.isDefault, mr.branch, mr.configurations, mr.licenses,
|
oar.modules map { mr =>
|
||||||
filterOutArtificialCallers(mr.callers)
|
ModuleReport(
|
||||||
)
|
mr.module,
|
||||||
})
|
mr.artifacts,
|
||||||
})
|
mr.missingArtifacts,
|
||||||
|
mr.status,
|
||||||
|
mr.publicationDate,
|
||||||
|
mr.resolver,
|
||||||
|
mr.artifactResolver,
|
||||||
|
mr.evicted,
|
||||||
|
mr.evictedData,
|
||||||
|
mr.evictedReason,
|
||||||
|
mr.problem,
|
||||||
|
mr.homepage,
|
||||||
|
mr.extraAttributes,
|
||||||
|
mr.isDefault,
|
||||||
|
mr.branch,
|
||||||
|
mr.configurations,
|
||||||
|
mr.licenses,
|
||||||
|
filterOutArtificialCallers(mr.callers)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
})
|
})
|
||||||
// #1763/#2030. Caller takes up 97% of space, so we need to shrink it down,
|
// #1763/#2030. Caller takes up 97% of space, so we need to shrink it down,
|
||||||
// but there are semantics associated with some of them.
|
// but there are semantics associated with some of them.
|
||||||
|
|
@ -49,7 +72,7 @@ private[sbt] object JsonUtil {
|
||||||
else {
|
else {
|
||||||
val nonArtificial = callers filter { c =>
|
val nonArtificial = callers filter { c =>
|
||||||
(c.caller.organization != sbtOrgTemp) &&
|
(c.caller.organization != sbtOrgTemp) &&
|
||||||
(c.caller.organization != fakeCallerOrganization)
|
(c.caller.organization != fakeCallerOrganization)
|
||||||
}
|
}
|
||||||
val interProj = (callers find { c =>
|
val interProj = (callers find { c =>
|
||||||
c.caller.organization == sbtOrgTemp
|
c.caller.organization == sbtOrgTemp
|
||||||
|
|
@ -57,18 +80,17 @@ private[sbt] object JsonUtil {
|
||||||
interProj ++ nonArtificial
|
interProj ++ nonArtificial
|
||||||
}
|
}
|
||||||
|
|
||||||
def fromLite(lite: UpdateReportLite, cachedDescriptor: File): UpdateReport =
|
def fromLite(lite: UpdateReportLite, cachedDescriptor: File): UpdateReport = {
|
||||||
{
|
val stats = UpdateStats(0L, 0L, 0L, false)
|
||||||
val stats = UpdateStats(0L, 0L, 0L, false)
|
val configReports = lite.configurations map { cr =>
|
||||||
val configReports = lite.configurations map { cr =>
|
val details = cr.details
|
||||||
val details = cr.details
|
val modules = details flatMap {
|
||||||
val modules = details flatMap {
|
_.modules filter { mr =>
|
||||||
_.modules filter { mr =>
|
!mr.evicted && mr.problem.isEmpty
|
||||||
!mr.evicted && mr.problem.isEmpty
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ConfigurationReport(cr.configuration, modules, details)
|
|
||||||
}
|
}
|
||||||
UpdateReport(cachedDescriptor, configReports, stats, Map.empty)
|
ConfigurationReport(cr.configuration, modules, details)
|
||||||
}
|
}
|
||||||
|
UpdateReport(cachedDescriptor, configReports, stats, Map.empty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,35 +19,121 @@ import Configurations.Optional
|
||||||
|
|
||||||
import org.apache.ivy.Ivy
|
import org.apache.ivy.Ivy
|
||||||
import org.apache.ivy.core.settings.IvySettings
|
import org.apache.ivy.core.settings.IvySettings
|
||||||
import org.apache.ivy.core.module.descriptor.{ DependencyArtifactDescriptor, DependencyDescriptor, License, ModuleDescriptor, ExcludeRule }
|
import org.apache.ivy.core.module.descriptor.{
|
||||||
|
DependencyArtifactDescriptor,
|
||||||
|
DependencyDescriptor,
|
||||||
|
License,
|
||||||
|
ModuleDescriptor,
|
||||||
|
ExcludeRule
|
||||||
|
}
|
||||||
import org.apache.ivy.plugins.resolver.{ ChainResolver, DependencyResolver, IBiblioResolver }
|
import org.apache.ivy.plugins.resolver.{ ChainResolver, DependencyResolver, IBiblioResolver }
|
||||||
import ivyint.CustomRemoteMavenResolver
|
import ivyint.CustomRemoteMavenResolver
|
||||||
import sbt.io.IO
|
import sbt.io.IO
|
||||||
|
|
||||||
object MakePom {
|
object MakePom {
|
||||||
|
|
||||||
/** True if the revision is an ivy-range, not a complete revision. */
|
/** True if the revision is an ivy-range, not a complete revision. */
|
||||||
def isDependencyVersionRange(revision: String): Boolean = VersionRange.isVersionRange(revision)
|
def isDependencyVersionRange(revision: String): Boolean = VersionRange.isVersionRange(revision)
|
||||||
|
|
||||||
/** Converts Ivy revision ranges to that of Maven POM */
|
/** Converts Ivy revision ranges to that of Maven POM */
|
||||||
def makeDependencyVersion(revision: String): String = VersionRange.fromIvyToMavenVersion(revision)
|
def makeDependencyVersion(revision: String): String =
|
||||||
|
VersionRange.fromIvyToMavenVersion(revision)
|
||||||
}
|
}
|
||||||
class MakePom(val log: Logger) {
|
class MakePom(val log: Logger) {
|
||||||
import MakePom._
|
import MakePom._
|
||||||
@deprecated("Use `write(Ivy, ModuleDescriptor, ModuleInfo, Option[Iterable[Configuration]], Set[String], NodeSeq, XNode => XNode, MavenRepository => Boolean, Boolean, File)` instead", "0.11.2")
|
@deprecated(
|
||||||
def write(ivy: Ivy, module: ModuleDescriptor, moduleInfo: ModuleInfo, configurations: Option[Iterable[Configuration]], extra: NodeSeq, process: XNode => XNode, filterRepositories: MavenRepository => Boolean, allRepositories: Boolean, output: File): Unit =
|
"Use `write(Ivy, ModuleDescriptor, ModuleInfo, Option[Iterable[Configuration]], Set[String], NodeSeq, XNode => XNode, MavenRepository => Boolean, Boolean, File)` instead",
|
||||||
write(ivy, module, moduleInfo: ModuleInfo, configurations: Option[Iterable[Configuration]], Set(Artifact.DefaultType), extra, process, filterRepositories, allRepositories, output)
|
"0.11.2"
|
||||||
def write(ivy: Ivy, module: ModuleDescriptor, moduleInfo: ModuleInfo, configurations: Option[Iterable[Configuration]], includeTypes: Set[String], extra: NodeSeq, process: XNode => XNode, filterRepositories: MavenRepository => Boolean, allRepositories: Boolean, output: File): Unit =
|
)
|
||||||
write(process(toPom(ivy, module, moduleInfo, configurations, includeTypes, extra, filterRepositories, allRepositories)), output)
|
def write(
|
||||||
|
ivy: Ivy,
|
||||||
|
module: ModuleDescriptor,
|
||||||
|
moduleInfo: ModuleInfo,
|
||||||
|
configurations: Option[Iterable[Configuration]],
|
||||||
|
extra: NodeSeq,
|
||||||
|
process: XNode => XNode,
|
||||||
|
filterRepositories: MavenRepository => Boolean,
|
||||||
|
allRepositories: Boolean,
|
||||||
|
output: File
|
||||||
|
): Unit =
|
||||||
|
write(
|
||||||
|
ivy,
|
||||||
|
module,
|
||||||
|
moduleInfo: ModuleInfo,
|
||||||
|
configurations: Option[Iterable[Configuration]],
|
||||||
|
Set(Artifact.DefaultType),
|
||||||
|
extra,
|
||||||
|
process,
|
||||||
|
filterRepositories,
|
||||||
|
allRepositories,
|
||||||
|
output
|
||||||
|
)
|
||||||
|
def write(
|
||||||
|
ivy: Ivy,
|
||||||
|
module: ModuleDescriptor,
|
||||||
|
moduleInfo: ModuleInfo,
|
||||||
|
configurations: Option[Iterable[Configuration]],
|
||||||
|
includeTypes: Set[String],
|
||||||
|
extra: NodeSeq,
|
||||||
|
process: XNode => XNode,
|
||||||
|
filterRepositories: MavenRepository => Boolean,
|
||||||
|
allRepositories: Boolean,
|
||||||
|
output: File
|
||||||
|
): Unit =
|
||||||
|
write(
|
||||||
|
process(
|
||||||
|
toPom(
|
||||||
|
ivy,
|
||||||
|
module,
|
||||||
|
moduleInfo,
|
||||||
|
configurations,
|
||||||
|
includeTypes,
|
||||||
|
extra,
|
||||||
|
filterRepositories,
|
||||||
|
allRepositories
|
||||||
|
)
|
||||||
|
),
|
||||||
|
output
|
||||||
|
)
|
||||||
// use \n as newline because toString uses PrettyPrinter, which hard codes line endings to be \n
|
// use \n as newline because toString uses PrettyPrinter, which hard codes line endings to be \n
|
||||||
def write(node: XNode, output: File): Unit = write(toString(node), output, "\n")
|
def write(node: XNode, output: File): Unit = write(toString(node), output, "\n")
|
||||||
def write(xmlString: String, output: File, newline: String): Unit =
|
def write(xmlString: String, output: File, newline: String): Unit =
|
||||||
IO.write(output, "<?xml version='1.0' encoding='" + IO.utf8.name + "'?>" + newline + xmlString)
|
IO.write(output, "<?xml version='1.0' encoding='" + IO.utf8.name + "'?>" + newline + xmlString)
|
||||||
|
|
||||||
def toString(node: XNode): String = new PrettyPrinter(1000, 4).format(node)
|
def toString(node: XNode): String = new PrettyPrinter(1000, 4).format(node)
|
||||||
@deprecated("Use `toPom(Ivy, ModuleDescriptor, ModuleInfo, Option[Iterable[Configuration]], Set[String], NodeSeq, MavenRepository => Boolean, Boolean)` instead", "0.11.2")
|
@deprecated(
|
||||||
def toPom(ivy: Ivy, module: ModuleDescriptor, moduleInfo: ModuleInfo, configurations: Option[Iterable[Configuration]], extra: NodeSeq, filterRepositories: MavenRepository => Boolean, allRepositories: Boolean): XNode =
|
"Use `toPom(Ivy, ModuleDescriptor, ModuleInfo, Option[Iterable[Configuration]], Set[String], NodeSeq, MavenRepository => Boolean, Boolean)` instead",
|
||||||
toPom(ivy, module, moduleInfo, configurations, Set(Artifact.DefaultType), extra, filterRepositories, allRepositories)
|
"0.11.2"
|
||||||
def toPom(ivy: Ivy, module: ModuleDescriptor, moduleInfo: ModuleInfo, configurations: Option[Iterable[Configuration]], includeTypes: Set[String], extra: NodeSeq, filterRepositories: MavenRepository => Boolean, allRepositories: Boolean): XNode =
|
)
|
||||||
|
def toPom(
|
||||||
|
ivy: Ivy,
|
||||||
|
module: ModuleDescriptor,
|
||||||
|
moduleInfo: ModuleInfo,
|
||||||
|
configurations: Option[Iterable[Configuration]],
|
||||||
|
extra: NodeSeq,
|
||||||
|
filterRepositories: MavenRepository => Boolean,
|
||||||
|
allRepositories: Boolean
|
||||||
|
): XNode =
|
||||||
|
toPom(
|
||||||
|
ivy,
|
||||||
|
module,
|
||||||
|
moduleInfo,
|
||||||
|
configurations,
|
||||||
|
Set(Artifact.DefaultType),
|
||||||
|
extra,
|
||||||
|
filterRepositories,
|
||||||
|
allRepositories
|
||||||
|
)
|
||||||
|
def toPom(
|
||||||
|
ivy: Ivy,
|
||||||
|
module: ModuleDescriptor,
|
||||||
|
moduleInfo: ModuleInfo,
|
||||||
|
configurations: Option[Iterable[Configuration]],
|
||||||
|
includeTypes: Set[String],
|
||||||
|
extra: NodeSeq,
|
||||||
|
filterRepositories: MavenRepository => Boolean,
|
||||||
|
allRepositories: Boolean
|
||||||
|
): XNode =
|
||||||
(<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
(<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
{ makeModuleID(module) }
|
{ makeModuleID(module) }
|
||||||
|
|
@ -65,81 +151,80 @@ class MakePom(val log: Logger) {
|
||||||
{ makeRepositories(ivy.getSettings, allRepositories, filterRepositories) }
|
{ makeRepositories(ivy.getSettings, allRepositories, filterRepositories) }
|
||||||
</project>)
|
</project>)
|
||||||
|
|
||||||
def makeModuleID(module: ModuleDescriptor): NodeSeq =
|
def makeModuleID(module: ModuleDescriptor): NodeSeq = {
|
||||||
{
|
val mrid = moduleDescriptor(module)
|
||||||
val mrid = moduleDescriptor(module)
|
val a: NodeSeq =
|
||||||
val a: NodeSeq =
|
(<groupId>{ mrid.getOrganisation }</groupId>
|
||||||
(<groupId>{ mrid.getOrganisation }</groupId>
|
<artifactId>{ mrid.getName }</artifactId>
|
||||||
<artifactId>{ mrid.getName }</artifactId>
|
<packaging>{ packaging(module) }</packaging>)
|
||||||
<packaging>{ packaging(module) }</packaging>)
|
val b: NodeSeq =
|
||||||
val b: NodeSeq =
|
((description(module.getDescription) ++
|
||||||
((description(module.getDescription) ++
|
homePage(module.getHomePage) ++
|
||||||
homePage(module.getHomePage) ++
|
revision(mrid.getRevision) ++
|
||||||
revision(mrid.getRevision) ++
|
licenses(module.getLicenses)): NodeSeq)
|
||||||
licenses(module.getLicenses)): NodeSeq)
|
a ++ b
|
||||||
a ++ b
|
}
|
||||||
}
|
|
||||||
|
|
||||||
def makeStartYear(moduleInfo: ModuleInfo): NodeSeq =
|
def makeStartYear(moduleInfo: ModuleInfo): NodeSeq =
|
||||||
moduleInfo.startYear match {
|
moduleInfo.startYear match {
|
||||||
case Some(y) => <inceptionYear>{ y }</inceptionYear>
|
case Some(y) => <inceptionYear>{ y }</inceptionYear>
|
||||||
case _ => NodeSeq.Empty
|
case _ => NodeSeq.Empty
|
||||||
}
|
}
|
||||||
def makeOrganization(moduleInfo: ModuleInfo): NodeSeq =
|
def makeOrganization(moduleInfo: ModuleInfo): NodeSeq = {
|
||||||
{
|
<organization>
|
||||||
<organization>
|
<name>{ moduleInfo.organizationName }</name>
|
||||||
<name>{ moduleInfo.organizationName }</name>
|
{
|
||||||
|
moduleInfo.organizationHomepage match {
|
||||||
|
case Some(h)=> <url>{ h }</url>
|
||||||
|
case _ => NodeSeq.Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</organization>
|
||||||
|
}
|
||||||
|
def makeScmInfo(moduleInfo: ModuleInfo): NodeSeq = {
|
||||||
|
moduleInfo.scmInfo match {
|
||||||
|
case Some(s) =>
|
||||||
|
<scm>
|
||||||
|
<url>{ s.browseUrl }</url>
|
||||||
|
<connection>{ s.connection }</connection>
|
||||||
|
{
|
||||||
|
s.devConnection match {
|
||||||
|
case Some(d)=> <developerConnection>{ d }</developerConnection>
|
||||||
|
case _=> NodeSeq.Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</scm>
|
||||||
|
case _ => NodeSeq.Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
def makeDeveloperInfo(moduleInfo: ModuleInfo): NodeSeq = {
|
||||||
|
if (moduleInfo.developers.nonEmpty) {
|
||||||
|
<developers>
|
||||||
{
|
{
|
||||||
moduleInfo.organizationHomepage match {
|
moduleInfo.developers.map { developer: Developer =>
|
||||||
case Some(h)=> <url>{ h }</url>
|
<developer>
|
||||||
case _ => NodeSeq.Empty
|
<id>{ developer.id }</id>
|
||||||
|
<name>{ developer.name }</name>
|
||||||
|
<email>{ developer.email }</email>
|
||||||
|
<url>{ developer.url }</url>
|
||||||
|
</developer>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</organization>
|
</developers>
|
||||||
}
|
} else NodeSeq.Empty
|
||||||
def makeScmInfo(moduleInfo: ModuleInfo): NodeSeq =
|
}
|
||||||
{
|
def makeProperties(module: ModuleDescriptor, dependencies: Seq[DependencyDescriptor]): NodeSeq = {
|
||||||
moduleInfo.scmInfo match {
|
val extra = IvySbt.getExtraAttributes(module)
|
||||||
case Some(s) =>
|
val depExtra = PomExtraDependencyAttributes.writeDependencyExtra(dependencies).mkString("\n")
|
||||||
<scm>
|
val allExtra =
|
||||||
<url>{ s.browseUrl }</url>
|
if (depExtra.isEmpty) extra
|
||||||
<connection>{ s.connection }</connection>
|
else extra.updated(PomExtraDependencyAttributes.ExtraAttributesKey, depExtra)
|
||||||
{
|
if (allExtra.isEmpty) NodeSeq.Empty else makeProperties(allExtra)
|
||||||
s.devConnection match {
|
}
|
||||||
case Some(d)=> <developerConnection>{ d }</developerConnection>
|
|
||||||
case _=> NodeSeq.Empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</scm>
|
|
||||||
case _ => NodeSeq.Empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
def makeDeveloperInfo(moduleInfo: ModuleInfo): NodeSeq =
|
|
||||||
{
|
|
||||||
if (moduleInfo.developers.nonEmpty) {
|
|
||||||
<developers>
|
|
||||||
{
|
|
||||||
moduleInfo.developers.map { developer: Developer =>
|
|
||||||
<developer>
|
|
||||||
<id>{ developer.id }</id>
|
|
||||||
<name>{ developer.name }</name>
|
|
||||||
<email>{ developer.email }</email>
|
|
||||||
<url>{ developer.url }</url>
|
|
||||||
</developer>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</developers>
|
|
||||||
} else NodeSeq.Empty
|
|
||||||
}
|
|
||||||
def makeProperties(module: ModuleDescriptor, dependencies: Seq[DependencyDescriptor]): NodeSeq =
|
|
||||||
{
|
|
||||||
val extra = IvySbt.getExtraAttributes(module)
|
|
||||||
val depExtra = PomExtraDependencyAttributes.writeDependencyExtra(dependencies).mkString("\n")
|
|
||||||
val allExtra = if (depExtra.isEmpty) extra else extra.updated(PomExtraDependencyAttributes.ExtraAttributesKey, depExtra)
|
|
||||||
if (allExtra.isEmpty) NodeSeq.Empty else makeProperties(allExtra)
|
|
||||||
}
|
|
||||||
def makeProperties(extra: Map[String, String]): NodeSeq = {
|
def makeProperties(extra: Map[String, String]): NodeSeq = {
|
||||||
def _extraAttributes(k: String) = if (k == PomExtraDependencyAttributes.ExtraAttributesKey) xmlSpacePreserve else scala.xml.Null
|
def _extraAttributes(k: String) =
|
||||||
|
if (k == PomExtraDependencyAttributes.ExtraAttributesKey) xmlSpacePreserve
|
||||||
|
else scala.xml.Null
|
||||||
<properties> {
|
<properties> {
|
||||||
for ((key, value) <- extra) yield (<x>{ value }</x>).copy(label = key, attributes = _extraAttributes(key))
|
for ((key, value) <- extra) yield (<x>{ value }</x>).copy(label = key, attributes = _extraAttributes(key))
|
||||||
} </properties>
|
} </properties>
|
||||||
|
|
@ -152,8 +237,10 @@ class MakePom(val log: Logger) {
|
||||||
*/
|
*/
|
||||||
def xmlSpacePreserve = new PrefixedAttribute("xml", "space", "preserve", scala.xml.Null)
|
def xmlSpacePreserve = new PrefixedAttribute("xml", "space", "preserve", scala.xml.Null)
|
||||||
|
|
||||||
def description(d: String) = if ((d eq null) || d.isEmpty) NodeSeq.Empty else <description>{ d }</description>
|
def description(d: String) =
|
||||||
def licenses(ls: Array[License]) = if (ls == null || ls.isEmpty) NodeSeq.Empty else <licenses>{ ls.map(license) }</licenses>
|
if ((d eq null) || d.isEmpty) NodeSeq.Empty else <description>{ d }</description>
|
||||||
|
def licenses(ls: Array[License]) =
|
||||||
|
if (ls == null || ls.isEmpty) NodeSeq.Empty else <licenses>{ ls.map(license) }</licenses>
|
||||||
def license(l: License) =
|
def license(l: License) =
|
||||||
<license>
|
<license>
|
||||||
<name>{ l.getName }</name>
|
<name>{ l.getName }</name>
|
||||||
|
|
@ -161,7 +248,8 @@ class MakePom(val log: Logger) {
|
||||||
<distribution>repo</distribution>
|
<distribution>repo</distribution>
|
||||||
</license>
|
</license>
|
||||||
def homePage(homePage: String) = if (homePage eq null) NodeSeq.Empty else <url>{ homePage }</url>
|
def homePage(homePage: String) = if (homePage eq null) NodeSeq.Empty else <url>{ homePage }</url>
|
||||||
def revision(version: String) = if (version ne null) <version>{ version }</version> else NodeSeq.Empty
|
def revision(version: String) =
|
||||||
|
if (version ne null) <version>{ version }</version> else NodeSeq.Empty
|
||||||
def packaging(module: ModuleDescriptor) =
|
def packaging(module: ModuleDescriptor) =
|
||||||
module.getAllArtifacts match {
|
module.getAllArtifacts match {
|
||||||
case Array() => "pom"
|
case Array() => "pom"
|
||||||
|
|
@ -177,10 +265,17 @@ class MakePom(val log: Logger) {
|
||||||
val IgnoreTypes: Set[String] = Set(Artifact.SourceType, Artifact.DocType, Artifact.PomType)
|
val IgnoreTypes: Set[String] = Set(Artifact.SourceType, Artifact.DocType, Artifact.PomType)
|
||||||
|
|
||||||
@deprecated("Use `makeDependencies` variant which takes excludes", "0.13.9")
|
@deprecated("Use `makeDependencies` variant which takes excludes", "0.13.9")
|
||||||
def makeDependencies(dependencies: Seq[DependencyDescriptor], includeTypes: Set[String]): NodeSeq =
|
def makeDependencies(
|
||||||
|
dependencies: Seq[DependencyDescriptor],
|
||||||
|
includeTypes: Set[String]
|
||||||
|
): NodeSeq =
|
||||||
makeDependencies(dependencies, includeTypes, Nil)
|
makeDependencies(dependencies, includeTypes, Nil)
|
||||||
|
|
||||||
def makeDependencies(dependencies: Seq[DependencyDescriptor], includeTypes: Set[String], excludes: Seq[ExcludeRule]): NodeSeq =
|
def makeDependencies(
|
||||||
|
dependencies: Seq[DependencyDescriptor],
|
||||||
|
includeTypes: Set[String],
|
||||||
|
excludes: Seq[ExcludeRule]
|
||||||
|
): NodeSeq =
|
||||||
if (dependencies.isEmpty)
|
if (dependencies.isEmpty)
|
||||||
NodeSeq.Empty
|
NodeSeq.Empty
|
||||||
else
|
else
|
||||||
|
|
@ -192,74 +287,96 @@ class MakePom(val log: Logger) {
|
||||||
def makeDependency(dependency: DependencyDescriptor, includeTypes: Set[String]): NodeSeq =
|
def makeDependency(dependency: DependencyDescriptor, includeTypes: Set[String]): NodeSeq =
|
||||||
makeDependency(dependency, includeTypes, Nil)
|
makeDependency(dependency, includeTypes, Nil)
|
||||||
|
|
||||||
def makeDependency(dependency: DependencyDescriptor, includeTypes: Set[String], excludes: Seq[ExcludeRule]): NodeSeq =
|
def makeDependency(
|
||||||
{
|
dependency: DependencyDescriptor,
|
||||||
val artifacts = dependency.getAllDependencyArtifacts
|
includeTypes: Set[String],
|
||||||
val includeArtifacts = artifacts.filter(d => includeTypes(d.getType))
|
excludes: Seq[ExcludeRule]
|
||||||
if (artifacts.isEmpty) {
|
): NodeSeq = {
|
||||||
val configs = dependency.getModuleConfigurations
|
val artifacts = dependency.getAllDependencyArtifacts
|
||||||
if (configs.filterNot(Set("sources", "docs")).nonEmpty) {
|
val includeArtifacts = artifacts.filter(d => includeTypes(d.getType))
|
||||||
val (scope, optional) = getScopeAndOptional(dependency.getModuleConfigurations)
|
if (artifacts.isEmpty) {
|
||||||
makeDependencyElem(dependency, scope, optional, None, None, excludes)
|
val configs = dependency.getModuleConfigurations
|
||||||
} else NodeSeq.Empty
|
if (configs.filterNot(Set("sources", "docs")).nonEmpty) {
|
||||||
} else if (includeArtifacts.isEmpty)
|
val (scope, optional) = getScopeAndOptional(dependency.getModuleConfigurations)
|
||||||
NodeSeq.Empty
|
makeDependencyElem(dependency, scope, optional, None, None, excludes)
|
||||||
else
|
} else NodeSeq.Empty
|
||||||
NodeSeq.fromSeq(artifacts.flatMap(a => makeDependencyElem(dependency, a, excludes)))
|
} else if (includeArtifacts.isEmpty)
|
||||||
}
|
NodeSeq.Empty
|
||||||
|
else
|
||||||
|
NodeSeq.fromSeq(artifacts.flatMap(a => makeDependencyElem(dependency, a, excludes)))
|
||||||
|
}
|
||||||
|
|
||||||
@deprecated("Use `makeDependencyElem` variant which takes excludes", "0.13.9")
|
@deprecated("Use `makeDependencyElem` variant which takes excludes", "0.13.9")
|
||||||
def makeDependencyElem(dependency: DependencyDescriptor, artifact: DependencyArtifactDescriptor): Option[Elem] =
|
def makeDependencyElem(
|
||||||
|
dependency: DependencyDescriptor,
|
||||||
|
artifact: DependencyArtifactDescriptor
|
||||||
|
): Option[Elem] =
|
||||||
makeDependencyElem(dependency, artifact, Nil)
|
makeDependencyElem(dependency, artifact, Nil)
|
||||||
|
|
||||||
def makeDependencyElem(dependency: DependencyDescriptor, artifact: DependencyArtifactDescriptor, excludes: Seq[ExcludeRule]): Option[Elem] =
|
def makeDependencyElem(
|
||||||
{
|
dependency: DependencyDescriptor,
|
||||||
val configs = artifact.getConfigurations.toList match {
|
artifact: DependencyArtifactDescriptor,
|
||||||
case Nil | "*" :: Nil => dependency.getModuleConfigurations
|
excludes: Seq[ExcludeRule]
|
||||||
case x => x.toArray
|
): Option[Elem] = {
|
||||||
}
|
val configs = artifact.getConfigurations.toList match {
|
||||||
if (!configs.forall(Set("sources", "docs"))) {
|
case Nil | "*" :: Nil => dependency.getModuleConfigurations
|
||||||
val (scope, optional) = getScopeAndOptional(configs)
|
case x => x.toArray
|
||||||
val classifier = artifactClassifier(artifact)
|
|
||||||
val baseType = artifactType(artifact)
|
|
||||||
val tpe = (classifier, baseType) match {
|
|
||||||
case (Some(c), Some(tpe)) if Artifact.classifierType(c) == tpe => None
|
|
||||||
case _ => baseType
|
|
||||||
}
|
|
||||||
Some(makeDependencyElem(dependency, scope, optional, classifier, tpe, excludes))
|
|
||||||
} else None
|
|
||||||
}
|
}
|
||||||
|
if (!configs.forall(Set("sources", "docs"))) {
|
||||||
|
val (scope, optional) = getScopeAndOptional(configs)
|
||||||
|
val classifier = artifactClassifier(artifact)
|
||||||
|
val baseType = artifactType(artifact)
|
||||||
|
val tpe = (classifier, baseType) match {
|
||||||
|
case (Some(c), Some(tpe)) if Artifact.classifierType(c) == tpe => None
|
||||||
|
case _ => baseType
|
||||||
|
}
|
||||||
|
Some(makeDependencyElem(dependency, scope, optional, classifier, tpe, excludes))
|
||||||
|
} else None
|
||||||
|
}
|
||||||
|
|
||||||
@deprecated("Use `makeDependencyElem` variant which takes excludes", "0.13.9")
|
@deprecated("Use `makeDependencyElem` variant which takes excludes", "0.13.9")
|
||||||
def makeDependencyElem(dependency: DependencyDescriptor, scope: Option[String], optional: Boolean, classifier: Option[String], tpe: Option[String]): Elem =
|
def makeDependencyElem(
|
||||||
|
dependency: DependencyDescriptor,
|
||||||
|
scope: Option[String],
|
||||||
|
optional: Boolean,
|
||||||
|
classifier: Option[String],
|
||||||
|
tpe: Option[String]
|
||||||
|
): Elem =
|
||||||
makeDependencyElem(dependency, scope, optional, classifier, tpe, Nil)
|
makeDependencyElem(dependency, scope, optional, classifier, tpe, Nil)
|
||||||
|
|
||||||
def makeDependencyElem(dependency: DependencyDescriptor, scope: Option[String], optional: Boolean, classifier: Option[String], tpe: Option[String], excludes: Seq[ExcludeRule]): Elem =
|
def makeDependencyElem(
|
||||||
{
|
dependency: DependencyDescriptor,
|
||||||
val mrid = dependency.getDependencyRevisionId
|
scope: Option[String],
|
||||||
<dependency>
|
optional: Boolean,
|
||||||
<groupId>{ mrid.getOrganisation }</groupId>
|
classifier: Option[String],
|
||||||
<artifactId>{ mrid.getName }</artifactId>
|
tpe: Option[String],
|
||||||
<version>{ makeDependencyVersion(mrid.getRevision) }</version>
|
excludes: Seq[ExcludeRule]
|
||||||
{ scopeElem(scope) }
|
): Elem = {
|
||||||
{ optionalElem(optional) }
|
val mrid = dependency.getDependencyRevisionId
|
||||||
{ classifierElem(classifier) }
|
<dependency>
|
||||||
{ typeElem(tpe) }
|
<groupId>{ mrid.getOrganisation }</groupId>
|
||||||
{ exclusions(dependency, excludes) }
|
<artifactId>{ mrid.getName }</artifactId>
|
||||||
</dependency>
|
<version>{ makeDependencyVersion(mrid.getRevision) }</version>
|
||||||
}
|
{ scopeElem(scope) }
|
||||||
|
{ optionalElem(optional) }
|
||||||
|
{ classifierElem(classifier) }
|
||||||
|
{ typeElem(tpe) }
|
||||||
|
{ exclusions(dependency, excludes) }
|
||||||
|
</dependency>
|
||||||
|
}
|
||||||
|
|
||||||
@deprecated("No longer used and will be removed.", "0.12.1")
|
@deprecated("No longer used and will be removed.", "0.12.1")
|
||||||
def classifier(dependency: DependencyDescriptor, includeTypes: Set[String]): NodeSeq =
|
def classifier(dependency: DependencyDescriptor, includeTypes: Set[String]): NodeSeq = {
|
||||||
{
|
val jarDep = dependency.getAllDependencyArtifacts.find(d => includeTypes(d.getType))
|
||||||
val jarDep = dependency.getAllDependencyArtifacts.find(d => includeTypes(d.getType))
|
jarDep match {
|
||||||
jarDep match {
|
case Some(a) => classifierElem(artifactClassifier(a))
|
||||||
case Some(a) => classifierElem(artifactClassifier(a))
|
case None => NodeSeq.Empty
|
||||||
case None => NodeSeq.Empty
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
def artifactType(artifact: DependencyArtifactDescriptor): Option[String] =
|
def artifactType(artifact: DependencyArtifactDescriptor): Option[String] =
|
||||||
Option(artifact.getType).flatMap { tpe => if (tpe == "jar") None else Some(tpe) }
|
Option(artifact.getType).flatMap { tpe =>
|
||||||
|
if (tpe == "jar") None else Some(tpe)
|
||||||
|
}
|
||||||
def typeElem(tpe: Option[String]): NodeSeq =
|
def typeElem(tpe: Option[String]): NodeSeq =
|
||||||
tpe match {
|
tpe match {
|
||||||
case Some(t) => <type>{ t }</type>
|
case Some(t) => <type>{ t }</type>
|
||||||
|
|
@ -275,11 +392,10 @@ class MakePom(val log: Logger) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@deprecated("No longer used and will be removed.", "0.12.1")
|
@deprecated("No longer used and will be removed.", "0.12.1")
|
||||||
def scopeAndOptional(dependency: DependencyDescriptor): NodeSeq =
|
def scopeAndOptional(dependency: DependencyDescriptor): NodeSeq = {
|
||||||
{
|
val (scope, opt) = getScopeAndOptional(dependency.getModuleConfigurations)
|
||||||
val (scope, opt) = getScopeAndOptional(dependency.getModuleConfigurations)
|
scopeElem(scope) ++ optionalElem(opt)
|
||||||
scopeElem(scope) ++ optionalElem(opt)
|
}
|
||||||
}
|
|
||||||
def scopeElem(scope: Option[String]): NodeSeq = scope match {
|
def scopeElem(scope: Option[String]): NodeSeq = scope match {
|
||||||
case None | Some(Configurations.Compile.name) => NodeSeq.Empty
|
case None | Some(Configurations.Compile.name) => NodeSeq.Empty
|
||||||
case Some(s) => <scope>{ s }</scope>
|
case Some(s) => <scope>{ s }</scope>
|
||||||
|
|
@ -287,59 +403,67 @@ class MakePom(val log: Logger) {
|
||||||
def optionalElem(opt: Boolean) = if (opt) <optional>true</optional> else NodeSeq.Empty
|
def optionalElem(opt: Boolean) = if (opt) <optional>true</optional> else NodeSeq.Empty
|
||||||
def moduleDescriptor(module: ModuleDescriptor) = module.getModuleRevisionId
|
def moduleDescriptor(module: ModuleDescriptor) = module.getModuleRevisionId
|
||||||
|
|
||||||
def getScopeAndOptional(confs: Array[String]): (Option[String], Boolean) =
|
def getScopeAndOptional(confs: Array[String]): (Option[String], Boolean) = {
|
||||||
{
|
val (opt, notOptional) = confs.partition(_ == Optional.name)
|
||||||
val (opt, notOptional) = confs.partition(_ == Optional.name)
|
val defaultNotOptional =
|
||||||
val defaultNotOptional = Configurations.defaultMavenConfigurations.find(notOptional contains _.name)
|
Configurations.defaultMavenConfigurations.find(notOptional contains _.name)
|
||||||
val scope = defaultNotOptional.map(_.name)
|
val scope = defaultNotOptional.map(_.name)
|
||||||
(scope, opt.nonEmpty)
|
(scope, opt.nonEmpty)
|
||||||
}
|
}
|
||||||
|
|
||||||
@deprecated("Use `exclusions` variant which takes excludes", "0.13.9")
|
@deprecated("Use `exclusions` variant which takes excludes", "0.13.9")
|
||||||
def exclusions(dependency: DependencyDescriptor): NodeSeq = exclusions(dependency, Nil)
|
def exclusions(dependency: DependencyDescriptor): NodeSeq = exclusions(dependency, Nil)
|
||||||
|
|
||||||
def exclusions(dependency: DependencyDescriptor, excludes: Seq[ExcludeRule]): NodeSeq =
|
def exclusions(dependency: DependencyDescriptor, excludes: Seq[ExcludeRule]): NodeSeq = {
|
||||||
{
|
val excl = dependency.getExcludeRules(dependency.getModuleConfigurations) ++ excludes
|
||||||
val excl = dependency.getExcludeRules(dependency.getModuleConfigurations) ++ excludes
|
val (warns, excls) = IvyUtil.separate(excl.map(makeExclusion))
|
||||||
val (warns, excls) = IvyUtil.separate(excl.map(makeExclusion))
|
if (warns.nonEmpty) log.warn(warns.mkString(IO.Newline))
|
||||||
if (warns.nonEmpty) log.warn(warns.mkString(IO.Newline))
|
if (excls.nonEmpty) <exclusions>{ excls }</exclusions>
|
||||||
if (excls.nonEmpty) <exclusions>{ excls }</exclusions>
|
else NodeSeq.Empty
|
||||||
else NodeSeq.Empty
|
}
|
||||||
}
|
def makeExclusion(exclRule: ExcludeRule): Either[String, NodeSeq] = {
|
||||||
def makeExclusion(exclRule: ExcludeRule): Either[String, NodeSeq] =
|
val m = exclRule.getId.getModuleId
|
||||||
{
|
val (g, a) = (m.getOrganisation, m.getName)
|
||||||
val m = exclRule.getId.getModuleId
|
if (g == null || g.isEmpty || g == "*" || a.isEmpty || a == "*")
|
||||||
val (g, a) = (m.getOrganisation, m.getName)
|
Left(
|
||||||
if (g == null || g.isEmpty || g == "*" || a.isEmpty || a == "*")
|
"Skipped generating '<exclusion/>' for %s. Dependency exclusion should have both 'org' and 'module' to comply with Maven POM's schema."
|
||||||
Left("Skipped generating '<exclusion/>' for %s. Dependency exclusion should have both 'org' and 'module' to comply with Maven POM's schema.".format(m))
|
.format(m)
|
||||||
else
|
)
|
||||||
Right(
|
else
|
||||||
<exclusion>
|
Right(
|
||||||
<groupId>{ g }</groupId>
|
<exclusion>
|
||||||
<artifactId>{ a }</artifactId>
|
<groupId>{ g }</groupId>
|
||||||
</exclusion>
|
<artifactId>{ a }</artifactId>
|
||||||
)
|
</exclusion>
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
def makeRepositories(settings: IvySettings, includeAll: Boolean, filterRepositories: MavenRepository => Boolean) =
|
def makeRepositories(
|
||||||
{
|
settings: IvySettings,
|
||||||
val repositories = if (includeAll) allResolvers(settings) else resolvers(settings.getDefaultResolver)
|
includeAll: Boolean,
|
||||||
val mavenRepositories =
|
filterRepositories: MavenRepository => Boolean
|
||||||
repositories.flatMap {
|
) = {
|
||||||
// TODO - Would it be ok if bintray were in the pom? We should avoid it for now.
|
val repositories =
|
||||||
case m: CustomRemoteMavenResolver if m.repo.root == JCenterRepository.root => Nil
|
if (includeAll) allResolvers(settings) else resolvers(settings.getDefaultResolver)
|
||||||
case m: IBiblioResolver if m.isM2compatible && m.getRoot == JCenterRepository.root => Nil
|
val mavenRepositories =
|
||||||
case m: CustomRemoteMavenResolver if m.repo.root != DefaultMavenRepository.root =>
|
repositories.flatMap {
|
||||||
MavenRepository(m.repo.name, m.repo.root) :: Nil
|
// TODO - Would it be ok if bintray were in the pom? We should avoid it for now.
|
||||||
case m: IBiblioResolver if m.isM2compatible && m.getRoot != DefaultMavenRepository.root =>
|
case m: CustomRemoteMavenResolver if m.repo.root == JCenterRepository.root => Nil
|
||||||
MavenRepository(m.getName, m.getRoot) :: Nil
|
case m: IBiblioResolver if m.isM2compatible && m.getRoot == JCenterRepository.root => Nil
|
||||||
case _ => Nil
|
case m: CustomRemoteMavenResolver if m.repo.root != DefaultMavenRepository.root =>
|
||||||
}
|
MavenRepository(m.repo.name, m.repo.root) :: Nil
|
||||||
val repositoryElements = mavenRepositories.filter(filterRepositories).map(mavenRepository)
|
case m: IBiblioResolver if m.isM2compatible && m.getRoot != DefaultMavenRepository.root =>
|
||||||
if (repositoryElements.isEmpty) repositoryElements else <repositories>{ repositoryElements }</repositories>
|
MavenRepository(m.getName, m.getRoot) :: Nil
|
||||||
}
|
case _ => Nil
|
||||||
def allResolvers(settings: IvySettings): Seq[DependencyResolver] = flatten(castResolvers(settings.getResolvers)).distinct
|
}
|
||||||
def flatten(rs: Seq[DependencyResolver]): Seq[DependencyResolver] = if (rs eq null) Nil else rs.flatMap(resolvers)
|
val repositoryElements = mavenRepositories.filter(filterRepositories).map(mavenRepository)
|
||||||
|
if (repositoryElements.isEmpty) repositoryElements
|
||||||
|
else <repositories>{ repositoryElements }</repositories>
|
||||||
|
}
|
||||||
|
def allResolvers(settings: IvySettings): Seq[DependencyResolver] =
|
||||||
|
flatten(castResolvers(settings.getResolvers)).distinct
|
||||||
|
def flatten(rs: Seq[DependencyResolver]): Seq[DependencyResolver] =
|
||||||
|
if (rs eq null) Nil else rs.flatMap(resolvers)
|
||||||
def resolvers(r: DependencyResolver): Seq[DependencyResolver] =
|
def resolvers(r: DependencyResolver): Seq[DependencyResolver] =
|
||||||
r match { case c: ChainResolver => flatten(castResolvers(c.getResolvers)); case _ => r :: Nil }
|
r match { case c: ChainResolver => flatten(castResolvers(c.getResolvers)); case _ => r :: Nil }
|
||||||
|
|
||||||
|
|
@ -349,7 +473,8 @@ class MakePom(val log: Logger) {
|
||||||
|
|
||||||
def toID(name: String) = checkID(name.filter(isValidIDCharacter).mkString, name)
|
def toID(name: String) = checkID(name.filter(isValidIDCharacter).mkString, name)
|
||||||
def isValidIDCharacter(c: Char) = c.isLetterOrDigit
|
def isValidIDCharacter(c: Char) = c.isLetterOrDigit
|
||||||
private def checkID(id: String, name: String) = if (id.isEmpty) sys.error("Could not convert '" + name + "' to an ID") else id
|
private def checkID(id: String, name: String) =
|
||||||
|
if (id.isEmpty) sys.error("Could not convert '" + name + "' to an ID") else id
|
||||||
def mavenRepository(repo: MavenRepository): XNode =
|
def mavenRepository(repo: MavenRepository): XNode =
|
||||||
mavenRepository(toID(repo.name), repo.name, repo.root)
|
mavenRepository(toID(repo.name), repo.name, repo.root)
|
||||||
def mavenRepository(id: String, name: String, root: String): XNode =
|
def mavenRepository(id: String, name: String, root: String): XNode =
|
||||||
|
|
@ -364,18 +489,19 @@ class MakePom(val log: Logger) {
|
||||||
* Retain dependencies only with the configurations given, or all public configurations of `module` if `configurations` is None.
|
* Retain dependencies only with the configurations given, or all public configurations of `module` if `configurations` is None.
|
||||||
* This currently only preserves the information required by makePom
|
* This currently only preserves the information required by makePom
|
||||||
*/
|
*/
|
||||||
private def depsInConfs(module: ModuleDescriptor, configurations: Option[Iterable[Configuration]]): Seq[DependencyDescriptor] =
|
private def depsInConfs(
|
||||||
{
|
module: ModuleDescriptor,
|
||||||
val keepConfigurations = IvySbt.getConfigurations(module, configurations)
|
configurations: Option[Iterable[Configuration]]
|
||||||
val keepSet = Set(keepConfigurations.toSeq: _*)
|
): Seq[DependencyDescriptor] = {
|
||||||
def translate(dependency: DependencyDescriptor) =
|
val keepConfigurations = IvySbt.getConfigurations(module, configurations)
|
||||||
{
|
val keepSet = Set(keepConfigurations.toSeq: _*)
|
||||||
val keep = dependency.getModuleConfigurations.filter(keepSet.contains)
|
def translate(dependency: DependencyDescriptor) = {
|
||||||
if (keep.isEmpty)
|
val keep = dependency.getModuleConfigurations.filter(keepSet.contains)
|
||||||
None
|
if (keep.isEmpty)
|
||||||
else // TODO: translate the dependency to contain only configurations to keep
|
None
|
||||||
Some(dependency)
|
else // TODO: translate the dependency to contain only configurations to keep
|
||||||
}
|
Some(dependency)
|
||||||
module.getDependencies flatMap translate
|
|
||||||
}
|
}
|
||||||
|
module.getDependencies flatMap translate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,17 +10,28 @@ import org.apache.ivy.core.{ cache, module, report, resolve, search }
|
||||||
import cache.ArtifactOrigin
|
import cache.ArtifactOrigin
|
||||||
import search.{ ModuleEntry, OrganisationEntry, RevisionEntry }
|
import search.{ ModuleEntry, OrganisationEntry, RevisionEntry }
|
||||||
import module.id.ModuleRevisionId
|
import module.id.ModuleRevisionId
|
||||||
import module.descriptor.{ Artifact => IArtifact, DefaultArtifact, DependencyDescriptor, ModuleDescriptor }
|
import module.descriptor.{
|
||||||
|
Artifact => IArtifact,
|
||||||
|
DefaultArtifact,
|
||||||
|
DependencyDescriptor,
|
||||||
|
ModuleDescriptor
|
||||||
|
}
|
||||||
import org.apache.ivy.plugins.namespace.Namespace
|
import org.apache.ivy.plugins.namespace.Namespace
|
||||||
import org.apache.ivy.plugins.resolver.ResolverSettings
|
import org.apache.ivy.plugins.resolver.ResolverSettings
|
||||||
import report.{ ArtifactDownloadReport, DownloadReport, DownloadStatus, MetadataArtifactDownloadReport }
|
import report.{
|
||||||
|
ArtifactDownloadReport,
|
||||||
|
DownloadReport,
|
||||||
|
DownloadStatus,
|
||||||
|
MetadataArtifactDownloadReport
|
||||||
|
}
|
||||||
import resolve.{ DownloadOptions, ResolveData, ResolvedModuleRevision }
|
import resolve.{ DownloadOptions, ResolveData, ResolvedModuleRevision }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Resolver that uses a predefined mapping from module ids to in-memory descriptors.
|
* A Resolver that uses a predefined mapping from module ids to in-memory descriptors.
|
||||||
* It does not handle artifacts.
|
* It does not handle artifacts.
|
||||||
*/
|
*/
|
||||||
class ProjectResolver(name: String, map: Map[ModuleRevisionId, ModuleDescriptor]) extends ResolverAdapter {
|
class ProjectResolver(name: String, map: Map[ModuleRevisionId, ModuleDescriptor])
|
||||||
|
extends ResolverAdapter {
|
||||||
def getName = name
|
def getName = name
|
||||||
def setName(name: String) = sys.error("Setting name not supported by ProjectResolver")
|
def setName(name: String) = sys.error("Setting name not supported by ProjectResolver")
|
||||||
override def toString = "ProjectResolver(" + name + ", mapped: " + map.keys.mkString(", ") + ")"
|
override def toString = "ProjectResolver(" + name + ", mapped: " + map.keys.mkString(", ") + ")"
|
||||||
|
|
@ -28,48 +39,47 @@ class ProjectResolver(name: String, map: Map[ModuleRevisionId, ModuleDescriptor]
|
||||||
def getDependency(dd: DependencyDescriptor, data: ResolveData): ResolvedModuleRevision =
|
def getDependency(dd: DependencyDescriptor, data: ResolveData): ResolvedModuleRevision =
|
||||||
getDependency(dd.getDependencyRevisionId).orNull
|
getDependency(dd.getDependencyRevisionId).orNull
|
||||||
|
|
||||||
private[this] def getDependency(revisionId: ModuleRevisionId): Option[ResolvedModuleRevision] =
|
private[this] def getDependency(revisionId: ModuleRevisionId): Option[ResolvedModuleRevision] = {
|
||||||
{
|
def constructResult(descriptor: ModuleDescriptor) =
|
||||||
def constructResult(descriptor: ModuleDescriptor) = new ResolvedModuleRevision(this, this, descriptor, report(revisionId), true)
|
new ResolvedModuleRevision(this, this, descriptor, report(revisionId), true)
|
||||||
map get revisionId map constructResult
|
map get revisionId map constructResult
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def getModuleDescriptor(revisionId: ModuleRevisionId): Option[ModuleDescriptor] = map.get(revisionId)
|
private[sbt] def getModuleDescriptor(revisionId: ModuleRevisionId): Option[ModuleDescriptor] =
|
||||||
|
map.get(revisionId)
|
||||||
|
|
||||||
def report(revisionId: ModuleRevisionId): MetadataArtifactDownloadReport =
|
def report(revisionId: ModuleRevisionId): MetadataArtifactDownloadReport = {
|
||||||
{
|
val artifact = DefaultArtifact.newIvyArtifact(revisionId, new Date)
|
||||||
val artifact = DefaultArtifact.newIvyArtifact(revisionId, new Date)
|
val r = new MetadataArtifactDownloadReport(artifact)
|
||||||
val r = new MetadataArtifactDownloadReport(artifact)
|
r.setSearched(false)
|
||||||
r.setSearched(false)
|
r.setDownloadStatus(DownloadStatus.FAILED)
|
||||||
r.setDownloadStatus(DownloadStatus.FAILED)
|
r
|
||||||
r
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// this resolver nevers locates artifacts, only resolves dependencies
|
// this resolver nevers locates artifacts, only resolves dependencies
|
||||||
def exists(artifact: IArtifact) = false
|
def exists(artifact: IArtifact) = false
|
||||||
def locate(artifact: IArtifact) = null
|
def locate(artifact: IArtifact) = null
|
||||||
def download(artifacts: Array[IArtifact], options: DownloadOptions): DownloadReport =
|
def download(artifacts: Array[IArtifact], options: DownloadOptions): DownloadReport = {
|
||||||
{
|
val r = new DownloadReport
|
||||||
val r = new DownloadReport
|
for (artifact <- artifacts)
|
||||||
for (artifact <- artifacts)
|
if (getDependency(artifact.getModuleRevisionId).isEmpty)
|
||||||
if (getDependency(artifact.getModuleRevisionId).isEmpty)
|
r.addArtifactReport(notDownloaded(artifact))
|
||||||
r.addArtifactReport(notDownloaded(artifact))
|
r
|
||||||
r
|
}
|
||||||
}
|
|
||||||
|
|
||||||
def download(artifact: ArtifactOrigin, options: DownloadOptions): ArtifactDownloadReport =
|
def download(artifact: ArtifactOrigin, options: DownloadOptions): ArtifactDownloadReport =
|
||||||
notDownloaded(artifact.getArtifact)
|
notDownloaded(artifact.getArtifact)
|
||||||
def findIvyFileRef(dd: DependencyDescriptor, data: ResolveData) = null
|
def findIvyFileRef(dd: DependencyDescriptor, data: ResolveData) = null
|
||||||
|
|
||||||
def notDownloaded(artifact: IArtifact): ArtifactDownloadReport =
|
def notDownloaded(artifact: IArtifact): ArtifactDownloadReport = {
|
||||||
{
|
val r = new ArtifactDownloadReport(artifact)
|
||||||
val r = new ArtifactDownloadReport(artifact)
|
r.setDownloadStatus(DownloadStatus.FAILED)
|
||||||
r.setDownloadStatus(DownloadStatus.FAILED)
|
r
|
||||||
r
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// doesn't support publishing
|
// doesn't support publishing
|
||||||
def publish(artifact: IArtifact, src: File, overwrite: Boolean) = sys.error("Publish not supported by ProjectResolver")
|
def publish(artifact: IArtifact, src: File, overwrite: Boolean) =
|
||||||
|
sys.error("Publish not supported by ProjectResolver")
|
||||||
def beginPublishTransaction(module: ModuleRevisionId, overwrite: Boolean): Unit = ()
|
def beginPublishTransaction(module: ModuleRevisionId, overwrite: Boolean): Unit = ()
|
||||||
def abortPublishTransaction(): Unit = ()
|
def abortPublishTransaction(): Unit = ()
|
||||||
def commitPublishTransaction(): Unit = ()
|
def commitPublishTransaction(): Unit = ()
|
||||||
|
|
@ -87,7 +97,10 @@ class ProjectResolver(name: String, map: Map[ModuleRevisionId, ModuleDescriptor]
|
||||||
|
|
||||||
def dumpSettings(): Unit = ()
|
def dumpSettings(): Unit = ()
|
||||||
def setSettings(settings: ResolverSettings): Unit = { this.settings = Some(settings) }
|
def setSettings(settings: ResolverSettings): Unit = { this.settings = Some(settings) }
|
||||||
def getRepositoryCacheManager = settings match { case Some(s) => s.getDefaultRepositoryCacheManager; case None => sys.error("No settings defined for ProjectResolver") }
|
def getRepositoryCacheManager = settings match {
|
||||||
|
case Some(s) => s.getDefaultRepositoryCacheManager;
|
||||||
|
case None => sys.error("No settings defined for ProjectResolver")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object ProjectResolver {
|
object ProjectResolver {
|
||||||
|
|
|
||||||
|
|
@ -12,16 +12,28 @@ import sbt.internal.util.complete.DefaultParsers._
|
||||||
private[sbt] object RepositoriesParser {
|
private[sbt] object RepositoriesParser {
|
||||||
|
|
||||||
private case class AfterPattern(artifactPattern: Option[String], flags: Int)
|
private case class AfterPattern(artifactPattern: Option[String], flags: Int)
|
||||||
final case class PredefinedRepository(override val id: xsbti.Predefined) extends xsbti.PredefinedRepository
|
final case class PredefinedRepository(override val id: xsbti.Predefined)
|
||||||
final case class MavenRepository(override val id: String, override val url: URL) extends xsbti.MavenRepository
|
extends xsbti.PredefinedRepository
|
||||||
final case class IvyRepository(override val id: String, override val url: URL, override val ivyPattern: String,
|
final case class MavenRepository(override val id: String, override val url: URL)
|
||||||
override val artifactPattern: String, override val mavenCompatible: Boolean, override val skipConsistencyCheck: Boolean,
|
extends xsbti.MavenRepository
|
||||||
override val descriptorOptional: Boolean, val bootOnly: Boolean) extends xsbti.IvyRepository
|
final case class IvyRepository(
|
||||||
|
override val id: String,
|
||||||
|
override val url: URL,
|
||||||
|
override val ivyPattern: String,
|
||||||
|
override val artifactPattern: String,
|
||||||
|
override val mavenCompatible: Boolean,
|
||||||
|
override val skipConsistencyCheck: Boolean,
|
||||||
|
override val descriptorOptional: Boolean,
|
||||||
|
val bootOnly: Boolean
|
||||||
|
) extends xsbti.IvyRepository
|
||||||
|
|
||||||
// Predefined repositories
|
// Predefined repositories
|
||||||
def local: Parser[xsbti.Repository] = "local" ^^^ new PredefinedRepository(xsbti.Predefined.Local)
|
def local: Parser[xsbti.Repository] =
|
||||||
def mavenLocal: Parser[xsbti.Repository] = "maven-local" ^^^ new PredefinedRepository(xsbti.Predefined.MavenLocal)
|
"local" ^^^ new PredefinedRepository(xsbti.Predefined.Local)
|
||||||
def mavenCentral: Parser[xsbti.Repository] = "maven-central" ^^^ new PredefinedRepository(xsbti.Predefined.MavenCentral)
|
def mavenLocal: Parser[xsbti.Repository] =
|
||||||
|
"maven-local" ^^^ new PredefinedRepository(xsbti.Predefined.MavenLocal)
|
||||||
|
def mavenCentral: Parser[xsbti.Repository] =
|
||||||
|
"maven-central" ^^^ new PredefinedRepository(xsbti.Predefined.MavenCentral)
|
||||||
def predefinedResolver: Parser[xsbti.Repository] = local | mavenLocal | mavenCentral
|
def predefinedResolver: Parser[xsbti.Repository] = local | mavenLocal | mavenCentral
|
||||||
|
|
||||||
// Options
|
// Options
|
||||||
|
|
@ -54,7 +66,16 @@ private[sbt] object RepositoriesParser {
|
||||||
// scalac complains about the recursion depth if we pattern match over `ap` directly.
|
// scalac complains about the recursion depth if we pattern match over `ap` directly.
|
||||||
ap match {
|
ap match {
|
||||||
case Some(AfterPattern(artifactPattern, Flags(dOpt, sc, bo, mc))) =>
|
case Some(AfterPattern(artifactPattern, Flags(dOpt, sc, bo, mc))) =>
|
||||||
new IvyRepository(name, uri.toURL, ivy, artifactPattern getOrElse ivy, mc, sc, dOpt, bo)
|
new IvyRepository(
|
||||||
|
name,
|
||||||
|
uri.toURL,
|
||||||
|
ivy,
|
||||||
|
artifactPattern getOrElse ivy,
|
||||||
|
mc,
|
||||||
|
sc,
|
||||||
|
dOpt,
|
||||||
|
bo
|
||||||
|
)
|
||||||
case None =>
|
case None =>
|
||||||
new IvyRepository(name, uri.toURL, ivy, ivy, false, false, false, false)
|
new IvyRepository(name, uri.toURL, ivy, ivy, false, false, false, false)
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +90,8 @@ private[sbt] object RepositoriesParser {
|
||||||
def apply(lines: Iterator[String]): Seq[xsbti.Repository] =
|
def apply(lines: Iterator[String]): Seq[xsbti.Repository] =
|
||||||
if (lines.isEmpty) Nil
|
if (lines.isEmpty) Nil
|
||||||
else {
|
else {
|
||||||
if (lines.next != "[repositories]") throw new Exception("Repositories file must start with '[repositories]'")
|
if (lines.next != "[repositories]")
|
||||||
|
throw new Exception("Repositories file must start with '[repositories]'")
|
||||||
lines.flatMap(getResolver(_)(resolver)).toList
|
lines.flatMap(getResolver(_)(resolver)).toList
|
||||||
}
|
}
|
||||||
def apply(str: String): Seq[xsbti.Repository] = apply(str.lines)
|
def apply(str: String): Seq[xsbti.Repository] = apply(str.lines)
|
||||||
|
|
@ -92,4 +114,4 @@ private[sbt] object RepositoriesParser {
|
||||||
Some((dOpt, sc, bo, mc))
|
Some((dOpt, sc, bo, mc))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,24 @@ import sbt.librarymanagement._
|
||||||
* 2. Have them per-project for easier cleaning (possible with standard cache, but central to this custom one).
|
* 2. Have them per-project for easier cleaning (possible with standard cache, but central to this custom one).
|
||||||
* 3. Cache location includes extra attributes so that cross builds of a plugin do not overwrite each other.
|
* 3. Cache location includes extra attributes so that cross builds of a plugin do not overwrite each other.
|
||||||
*/
|
*/
|
||||||
private[sbt] final class ResolutionCache(base: File, settings: IvySettings) extends ResolutionCacheManager {
|
private[sbt] final class ResolutionCache(base: File, settings: IvySettings)
|
||||||
|
extends ResolutionCacheManager {
|
||||||
private[this] def resolvedFileInCache(m: ModuleRevisionId, name: String, ext: String): File = {
|
private[this] def resolvedFileInCache(m: ModuleRevisionId, name: String, ext: String): File = {
|
||||||
val p = ResolvedPattern
|
val p = ResolvedPattern
|
||||||
val f = IvyPatternHelper.substitute(p, m.getOrganisation, m.getName, m.getBranch, m.getRevision, name, name, ext, null, null, m.getAttributes, null)
|
val f = IvyPatternHelper.substitute(
|
||||||
|
p,
|
||||||
|
m.getOrganisation,
|
||||||
|
m.getName,
|
||||||
|
m.getBranch,
|
||||||
|
m.getRevision,
|
||||||
|
name,
|
||||||
|
name,
|
||||||
|
ext,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
m.getAttributes,
|
||||||
|
null
|
||||||
|
)
|
||||||
new File(base, f)
|
new File(base, f)
|
||||||
}
|
}
|
||||||
private[this] val reportBase: File = new File(base, ReportDirectory)
|
private[this] val reportBase: File = new File(base, ReportDirectory)
|
||||||
|
|
@ -62,11 +76,16 @@ private[sbt] final class ResolutionCache(base: File, settings: IvySettings) exte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private[sbt] object ResolutionCache {
|
private[sbt] object ResolutionCache {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes cached files from the resolution cache for the module with ID `mrid`
|
* Removes cached files from the resolution cache for the module with ID `mrid`
|
||||||
* and the resolveId (as set on `ResolveOptions`).
|
* and the resolveId (as set on `ResolveOptions`).
|
||||||
*/
|
*/
|
||||||
private[sbt] def cleanModule(mrid: ModuleRevisionId, resolveId: String, manager: ResolutionCacheManager): Unit = {
|
private[sbt] def cleanModule(
|
||||||
|
mrid: ModuleRevisionId,
|
||||||
|
resolveId: String,
|
||||||
|
manager: ResolutionCacheManager
|
||||||
|
): Unit = {
|
||||||
val files =
|
val files =
|
||||||
Option(manager.getResolvedIvyFileInCache(mrid)).toList :::
|
Option(manager.getResolvedIvyFileInCache(mrid)).toList :::
|
||||||
Option(manager.getResolvedIvyPropertiesInCache(mrid)).toList :::
|
Option(manager.getResolvedIvyPropertiesInCache(mrid)).toList :::
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ abstract class SbtExclusionRuleFunctions {
|
||||||
|
|
||||||
def apply(organization: String): SbtExclusionRule = apply(organization, "*")
|
def apply(organization: String): SbtExclusionRule = apply(organization, "*")
|
||||||
|
|
||||||
implicit def groupIdToExclusionRule(organization: GroupID): SbtExclusionRule = apply(organization.groupID)
|
implicit def groupIdToExclusionRule(organization: GroupID): SbtExclusionRule =
|
||||||
|
apply(organization.groupID)
|
||||||
implicit def stringToExclusionRule(organization: String): SbtExclusionRule = apply(organization)
|
implicit def stringToExclusionRule(organization: String): SbtExclusionRule = apply(organization)
|
||||||
|
|
||||||
implicit def groupArtifactIDToExclusionRule(gaid: GroupArtifactID): SbtExclusionRule =
|
implicit def groupArtifactIDToExclusionRule(gaid: GroupArtifactID): SbtExclusionRule =
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,12 @@ package sbt.internal.librarymanagement
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
object StringUtilities {
|
object StringUtilities {
|
||||||
@deprecated("Different use cases require different normalization. Use Project.normalizeModuleID or normalizeProjectID instead.", "0.13.0")
|
@deprecated(
|
||||||
|
"Different use cases require different normalization. Use Project.normalizeModuleID or normalizeProjectID instead.",
|
||||||
|
"0.13.0"
|
||||||
|
)
|
||||||
def normalize(s: String) = s.toLowerCase(Locale.ENGLISH).replaceAll("""\W+""", "-")
|
def normalize(s: String) = s.toLowerCase(Locale.ENGLISH).replaceAll("""\W+""", "-")
|
||||||
def nonEmpty(s: String, label: String): Unit = require(s.trim.length > 0, label + " cannot be empty.")
|
def nonEmpty(s: String, label: String): Unit =
|
||||||
|
require(s.trim.length > 0, label + " cannot be empty.")
|
||||||
def appendable(s: String) = if (s.isEmpty) "" else "_" + s
|
def appendable(s: String) = if (s.isEmpty) "" else "_" + s
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,14 @@ package internal
|
||||||
package librarymanagement
|
package librarymanagement
|
||||||
|
|
||||||
object VersionRange {
|
object VersionRange {
|
||||||
|
|
||||||
/** True if the revision is an ivy-range, not a complete revision. */
|
/** True if the revision is an ivy-range, not a complete revision. */
|
||||||
def isVersionRange(revision: String): Boolean = {
|
def isVersionRange(revision: String): Boolean = {
|
||||||
(revision endsWith "+") ||
|
(revision endsWith "+") ||
|
||||||
(revision contains "[") ||
|
(revision contains "[") ||
|
||||||
(revision contains "]") ||
|
(revision contains "]") ||
|
||||||
(revision contains "(") ||
|
(revision contains "(") ||
|
||||||
(revision contains ")")
|
(revision contains ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assuming Ivy is used to resolve conflict, this removes the version range
|
// Assuming Ivy is used to resolve conflict, this removes the version range
|
||||||
|
|
@ -50,13 +51,15 @@ object VersionRange {
|
||||||
val maxDigit = 5
|
val maxDigit = 5
|
||||||
try {
|
try {
|
||||||
revision match {
|
revision match {
|
||||||
case "+" => "[0,)"
|
case "+" => "[0,)"
|
||||||
case DotPlusPattern(base) => plusRange(base)
|
case DotPlusPattern(base) => plusRange(base)
|
||||||
// This is a heuristic. Maven just doesn't support Ivy's notions of 1+, so
|
// This is a heuristic. Maven just doesn't support Ivy's notions of 1+, so
|
||||||
// we assume version ranges never go beyond 5 siginificant digits.
|
// we assume version ranges never go beyond 5 siginificant digits.
|
||||||
case NumPlusPattern(tail) => (0 until maxDigit).map(plusRange(tail, _)).mkString(",")
|
case NumPlusPattern(tail) => (0 until maxDigit).map(plusRange(tail, _)).mkString(",")
|
||||||
case DotNumPlusPattern(base, tail) => (0 until maxDigit).map(plusRange(base + "." + tail, _)).mkString(",")
|
case DotNumPlusPattern(base, tail) =>
|
||||||
case rev if rev endsWith "+" => sys.error(s"dynamic revision '$rev' cannot be translated to POM")
|
(0 until maxDigit).map(plusRange(base + "." + tail, _)).mkString(",")
|
||||||
|
case rev if rev endsWith "+" =>
|
||||||
|
sys.error(s"dynamic revision '$rev' cannot be translated to POM")
|
||||||
case rev if startSym(rev(0)) && stopSym(rev(rev.length - 1)) =>
|
case rev if startSym(rev(0)) && stopSym(rev(rev.length - 1)) =>
|
||||||
val start = rev(0)
|
val start = rev(0)
|
||||||
val stop = rev(rev.length - 1)
|
val stop = rev(rev.length - 1)
|
||||||
|
|
@ -79,5 +82,6 @@ object VersionRange {
|
||||||
|
|
||||||
private[this] val startSym = Set(']', '[', '(')
|
private[this] val startSym = Set(']', '[', '(')
|
||||||
private[this] val stopSym = Set(']', '[', ')')
|
private[this] val stopSym = Set(']', '[', ')')
|
||||||
private[this] val MavenVersionSetPattern = """([\]\[\(])([\w\.\-]+)?(,)?([\w\.\-]+)?([\]\[\)])(,.+)?""".r
|
private[this] val MavenVersionSetPattern =
|
||||||
|
"""([\]\[\(])([\w\.\-]+)?(,)?([\w\.\-]+)?([\]\[\)])(,.+)?""".r
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,65 +12,73 @@ object CrossVersionUtil {
|
||||||
val TransitionSbtVersion = "0.12"
|
val TransitionSbtVersion = "0.12"
|
||||||
|
|
||||||
def isFull(s: String): Boolean = (s == trueString) || (s == fullString)
|
def isFull(s: String): Boolean = (s == trueString) || (s == fullString)
|
||||||
def isDisabled(s: String): Boolean = (s == falseString) || (s == noneString) || (s == disabledString)
|
def isDisabled(s: String): Boolean =
|
||||||
|
(s == falseString) || (s == noneString) || (s == disabledString)
|
||||||
def isBinary(s: String): Boolean = (s == binaryString)
|
def isBinary(s: String): Boolean = (s == binaryString)
|
||||||
|
|
||||||
private lazy val intPattern = """\d{1,10}"""
|
private lazy val intPattern = """\d{1,10}"""
|
||||||
private lazy val basicVersion = """(""" + intPattern + """)\.(""" + intPattern + """)\.(""" + intPattern + """)"""
|
private lazy val basicVersion = """(""" + intPattern + """)\.(""" + intPattern + """)\.(""" + intPattern + """)"""
|
||||||
|
|
||||||
private[sbt] def isSbtApiCompatible(v: String): Boolean = sbtApiVersion(v).isDefined
|
private[sbt] def isSbtApiCompatible(v: String): Boolean = sbtApiVersion(v).isDefined
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns sbt binary interface x.y API compatible with the given version string v.
|
* Returns sbt binary interface x.y API compatible with the given version string v.
|
||||||
* RCs for x.y.0 are considered API compatible.
|
* RCs for x.y.0 are considered API compatible.
|
||||||
* Compatibile versions include 0.12.0-1 and 0.12.0-RC1 for Some(0, 12).
|
* Compatibile versions include 0.12.0-1 and 0.12.0-RC1 for Some(0, 12).
|
||||||
*/
|
*/
|
||||||
private[sbt] def sbtApiVersion(v: String): Option[(Int, Int)] =
|
private[sbt] def sbtApiVersion(v: String): Option[(Int, Int)] = {
|
||||||
{
|
val ReleaseV = (basicVersion + """(-\d+)?""").r
|
||||||
val ReleaseV = (basicVersion + """(-\d+)?""").r
|
val CandidateV = (basicVersion + """(-RC\d+)""").r
|
||||||
val CandidateV = (basicVersion + """(-RC\d+)""").r
|
val NonReleaseV = (basicVersion + """([-\w+]*)""").r
|
||||||
val NonReleaseV = (basicVersion + """([-\w+]*)""").r
|
v match {
|
||||||
v match {
|
case ReleaseV(x, y, z, ht) => Some((x.toInt, y.toInt))
|
||||||
case ReleaseV(x, y, z, ht) => Some((x.toInt, y.toInt))
|
case CandidateV(x, y, z, ht) => Some((x.toInt, y.toInt))
|
||||||
case CandidateV(x, y, z, ht) => Some((x.toInt, y.toInt))
|
case NonReleaseV(x, y, z, ht) if z.toInt > 0 => Some((x.toInt, y.toInt))
|
||||||
case NonReleaseV(x, y, z, ht) if z.toInt > 0 => Some((x.toInt, y.toInt))
|
case _ => None
|
||||||
case _ => None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private[sbt] def isScalaApiCompatible(v: String): Boolean = scalaApiVersion(v).isDefined
|
private[sbt] def isScalaApiCompatible(v: String): Boolean = scalaApiVersion(v).isDefined
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns Scala binary interface x.y API compatible with the given version string v.
|
* Returns Scala binary interface x.y API compatible with the given version string v.
|
||||||
* Compatibile versions include 2.10.0-1 and 2.10.1-M1 for Some(2, 10), but not 2.10.0-RC1.
|
* Compatibile versions include 2.10.0-1 and 2.10.1-M1 for Some(2, 10), but not 2.10.0-RC1.
|
||||||
*/
|
*/
|
||||||
private[sbt] def scalaApiVersion(v: String): Option[(Int, Int)] =
|
private[sbt] def scalaApiVersion(v: String): Option[(Int, Int)] = {
|
||||||
{
|
val ReleaseV = (basicVersion + """(-\d+)?""").r
|
||||||
val ReleaseV = (basicVersion + """(-\d+)?""").r
|
val BinCompatV = (basicVersion + """-bin(-.*)?""").r
|
||||||
val BinCompatV = (basicVersion + """-bin(-.*)?""").r
|
val NonReleaseV = (basicVersion + """(-\w+)""").r
|
||||||
val NonReleaseV = (basicVersion + """(-\w+)""").r
|
v match {
|
||||||
v match {
|
case ReleaseV(x, y, z, ht) => Some((x.toInt, y.toInt))
|
||||||
case ReleaseV(x, y, z, ht) => Some((x.toInt, y.toInt))
|
case BinCompatV(x, y, z, ht) => Some((x.toInt, y.toInt))
|
||||||
case BinCompatV(x, y, z, ht) => Some((x.toInt, y.toInt))
|
case NonReleaseV(x, y, z, ht) if z.toInt > 0 => Some((x.toInt, y.toInt))
|
||||||
case NonReleaseV(x, y, z, ht) if z.toInt > 0 => Some((x.toInt, y.toInt))
|
case _ => None
|
||||||
case _ => None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
private[sbt] val PartialVersion = ("""(""" + intPattern + """)\.(""" + intPattern + """)(?:\..+)?""").r
|
}
|
||||||
|
private[sbt] val PartialVersion =
|
||||||
|
("""(""" + intPattern + """)\.(""" + intPattern + """)(?:\..+)?""").r
|
||||||
private[sbt] def partialVersion(s: String): Option[(Int, Int)] =
|
private[sbt] def partialVersion(s: String): Option[(Int, Int)] =
|
||||||
s match {
|
s match {
|
||||||
case PartialVersion(major, minor) => Some((major.toInt, minor.toInt))
|
case PartialVersion(major, minor) => Some((major.toInt, minor.toInt))
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
}
|
||||||
def binaryScalaVersion(full: String): String = binaryVersionWithApi(full, TransitionScalaVersion)(scalaApiVersion)
|
def binaryScalaVersion(full: String): String =
|
||||||
def binarySbtVersion(full: String): String = binaryVersionWithApi(full, TransitionSbtVersion)(sbtApiVersion)
|
binaryVersionWithApi(full, TransitionScalaVersion)(scalaApiVersion)
|
||||||
private[sbt] def binaryVersion(full: String, cutoff: String): String = binaryVersionWithApi(full, cutoff)(scalaApiVersion)
|
def binarySbtVersion(full: String): String =
|
||||||
|
binaryVersionWithApi(full, TransitionSbtVersion)(sbtApiVersion)
|
||||||
|
private[sbt] def binaryVersion(full: String, cutoff: String): String =
|
||||||
|
binaryVersionWithApi(full, cutoff)(scalaApiVersion)
|
||||||
private[this] def isNewer(major: Int, minor: Int, minMajor: Int, minMinor: Int): Boolean =
|
private[this] def isNewer(major: Int, minor: Int, minMajor: Int, minMinor: Int): Boolean =
|
||||||
major > minMajor || (major == minMajor && minor >= minMinor)
|
major > minMajor || (major == minMajor && minor >= minMinor)
|
||||||
private[this] def binaryVersionWithApi(full: String, cutoff: String)(apiVersion: String => Option[(Int, Int)]): String =
|
private[this] def binaryVersionWithApi(full: String, cutoff: String)(
|
||||||
{
|
apiVersion: String => Option[(Int, Int)]
|
||||||
def sub(major: Int, minor: Int) = major + "." + minor
|
): String = {
|
||||||
(apiVersion(full), partialVersion(cutoff)) match {
|
def sub(major: Int, minor: Int) = major + "." + minor
|
||||||
case (Some((major, minor)), None) => sub(major, minor)
|
(apiVersion(full), partialVersion(cutoff)) match {
|
||||||
case (Some((major, minor)), Some((minMajor, minMinor))) if isNewer(major, minor, minMajor, minMinor) => sub(major, minor)
|
case (Some((major, minor)), None) => sub(major, minor)
|
||||||
case _ => full
|
case (Some((major, minor)), Some((minMajor, minMinor)))
|
||||||
}
|
if isNewer(major, minor, minMajor, minMinor) =>
|
||||||
|
sub(major, minor)
|
||||||
|
case _ => full
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,23 @@ trait UpdateOptionsFormat { self: BasicJsonProtocol =>
|
||||||
|
|
||||||
implicit lazy val UpdateOptionsFormat: JsonFormat[UpdateOptions] =
|
implicit lazy val UpdateOptionsFormat: JsonFormat[UpdateOptions] =
|
||||||
project(
|
project(
|
||||||
(uo: UpdateOptions) => (
|
(uo: UpdateOptions) =>
|
||||||
uo.circularDependencyLevel.name,
|
(
|
||||||
uo.interProjectFirst,
|
uo.circularDependencyLevel.name,
|
||||||
uo.latestSnapshots,
|
uo.interProjectFirst,
|
||||||
uo.consolidatedResolution,
|
uo.latestSnapshots,
|
||||||
uo.cachedResolution
|
uo.consolidatedResolution,
|
||||||
|
uo.cachedResolution
|
||||||
),
|
),
|
||||||
(xs: (String, Boolean, Boolean, Boolean, Boolean)) =>
|
(xs: (String, Boolean, Boolean, Boolean, Boolean)) =>
|
||||||
new UpdateOptions(levels(xs._1), xs._2, xs._3, xs._4, xs._5, ConvertResolver.defaultConvert)
|
new UpdateOptions(
|
||||||
|
levels(xs._1),
|
||||||
|
xs._2,
|
||||||
|
xs._3,
|
||||||
|
xs._4,
|
||||||
|
xs._5,
|
||||||
|
ConvertResolver.defaultConvert
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val levels: Map[String, CircularDependencyLevel] = Map(
|
private val levels: Map[String, CircularDependencyLevel] = Map(
|
||||||
|
|
|
||||||
|
|
@ -8,58 +8,51 @@ import StringUtilities.nonEmpty
|
||||||
import sbt.librarymanagement._
|
import sbt.librarymanagement._
|
||||||
|
|
||||||
trait DependencyBuilders {
|
trait DependencyBuilders {
|
||||||
final implicit def toGroupID(groupID: String): GroupID =
|
final implicit def toGroupID(groupID: String): GroupID = {
|
||||||
{
|
nonEmpty(groupID, "Group ID")
|
||||||
nonEmpty(groupID, "Group ID")
|
new GroupID(groupID)
|
||||||
new GroupID(groupID)
|
}
|
||||||
}
|
final implicit def toRepositoryName(name: String): RepositoryName = {
|
||||||
final implicit def toRepositoryName(name: String): RepositoryName =
|
nonEmpty(name, "Repository name")
|
||||||
{
|
new RepositoryName(name)
|
||||||
nonEmpty(name, "Repository name")
|
}
|
||||||
new RepositoryName(name)
|
final implicit def moduleIDConfigurable(m: ModuleID): ModuleIDConfigurable = {
|
||||||
}
|
require(m.configurations.isEmpty, "Configurations already specified for module " + m)
|
||||||
final implicit def moduleIDConfigurable(m: ModuleID): ModuleIDConfigurable =
|
new ModuleIDConfigurable(m)
|
||||||
{
|
}
|
||||||
require(m.configurations.isEmpty, "Configurations already specified for module " + m)
|
|
||||||
new ModuleIDConfigurable(m)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final class GroupID private[sbt] (private[sbt] val groupID: String) {
|
final class GroupID private[sbt] (private[sbt] val groupID: String) {
|
||||||
def %(artifactID: String) = groupArtifact(artifactID, Disabled())
|
def %(artifactID: String) = groupArtifact(artifactID, Disabled())
|
||||||
def %%(artifactID: String): GroupArtifactID = groupArtifact(artifactID, CrossVersion.binary)
|
def %%(artifactID: String): GroupArtifactID = groupArtifact(artifactID, CrossVersion.binary)
|
||||||
|
|
||||||
private def groupArtifact(artifactID: String, cross: CrossVersion) =
|
private def groupArtifact(artifactID: String, cross: CrossVersion) = {
|
||||||
{
|
nonEmpty(artifactID, "Artifact ID")
|
||||||
nonEmpty(artifactID, "Artifact ID")
|
new GroupArtifactID(groupID, artifactID, cross)
|
||||||
new GroupArtifactID(groupID, artifactID, cross)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
final class GroupArtifactID private[sbt] (
|
final class GroupArtifactID private[sbt] (
|
||||||
private[sbt] val groupID: String,
|
private[sbt] val groupID: String,
|
||||||
private[sbt] val artifactID: String,
|
private[sbt] val artifactID: String,
|
||||||
private[sbt] val crossVersion: CrossVersion
|
private[sbt] val crossVersion: CrossVersion
|
||||||
) {
|
) {
|
||||||
def %(revision: String): ModuleID =
|
def %(revision: String): ModuleID = {
|
||||||
{
|
nonEmpty(revision, "Revision")
|
||||||
nonEmpty(revision, "Revision")
|
ModuleID(groupID, artifactID, revision).cross(crossVersion)
|
||||||
ModuleID(groupID, artifactID, revision).cross(crossVersion)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
final class ModuleIDConfigurable private[sbt] (moduleID: ModuleID) {
|
final class ModuleIDConfigurable private[sbt] (moduleID: ModuleID) {
|
||||||
def %(configuration: Configuration): ModuleID = %(configuration.name)
|
def %(configuration: Configuration): ModuleID = %(configuration.name)
|
||||||
|
|
||||||
def %(configurations: String): ModuleID =
|
def %(configurations: String): ModuleID = {
|
||||||
{
|
nonEmpty(configurations, "Configurations")
|
||||||
nonEmpty(configurations, "Configurations")
|
val c = configurations
|
||||||
val c = configurations
|
moduleID.withConfigurations(configurations = Some(c))
|
||||||
moduleID.withConfigurations(configurations = Some(c))
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
final class RepositoryName private[sbt] (name: String) {
|
final class RepositoryName private[sbt] (name: String) {
|
||||||
def at(location: String) =
|
def at(location: String) = {
|
||||||
{
|
nonEmpty(location, "Repository location")
|
||||||
nonEmpty(location, "Repository location")
|
MavenRepository(name, location)
|
||||||
MavenRepository(name, location)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -5,8 +5,7 @@ import org.apache.ivy.plugins.resolver.DependencyResolver
|
||||||
import sbt.librarymanagement._
|
import sbt.librarymanagement._
|
||||||
|
|
||||||
// These are placeholder traits for sbt-aether-resolver
|
// These are placeholder traits for sbt-aether-resolver
|
||||||
trait CustomMavenResolver extends DependencyResolver {
|
trait CustomMavenResolver extends DependencyResolver {}
|
||||||
}
|
|
||||||
trait CustomRemoteMavenResolver extends CustomMavenResolver {
|
trait CustomRemoteMavenResolver extends CustomMavenResolver {
|
||||||
def repo: MavenRepository
|
def repo: MavenRepository
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,9 @@ object ErrorMessageAuthenticator {
|
||||||
case originalOpt => installIntoIvyImpl(originalOpt)
|
case originalOpt => installIntoIvyImpl(originalOpt)
|
||||||
} catch {
|
} catch {
|
||||||
case t: Throwable =>
|
case t: Throwable =>
|
||||||
Message.debug("Error occurred while trying to install debug messages into Ivy Authentication" + t.getMessage)
|
Message.debug(
|
||||||
|
"Error occurred while trying to install debug messages into Ivy Authentication" + t.getMessage
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Some(ivy)
|
Some(ivy)
|
||||||
}
|
}
|
||||||
|
|
@ -57,8 +59,10 @@ object ErrorMessageAuthenticator {
|
||||||
catch {
|
catch {
|
||||||
case e: SecurityException if !securityWarningLogged =>
|
case e: SecurityException if !securityWarningLogged =>
|
||||||
securityWarningLogged = true
|
securityWarningLogged = true
|
||||||
Message.warn("Not enough permissions to set the ErrorMessageAuthenticator. "
|
Message.warn(
|
||||||
+ "Helpful debug messages disabled!");
|
"Not enough permissions to set the ErrorMessageAuthenticator. "
|
||||||
|
+ "Helpful debug messages disabled!"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// We will try to use the original authenticator as backup authenticator.
|
// We will try to use the original authenticator as backup authenticator.
|
||||||
// Since there is no getter available, so try to use some reflection to
|
// Since there is no getter available, so try to use some reflection to
|
||||||
|
|
@ -73,6 +77,7 @@ object ErrorMessageAuthenticator {
|
||||||
doInstallIfIvy(originalAuthenticator)
|
doInstallIfIvy(originalAuthenticator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An authenticator which just delegates to a previous authenticator and issues *nice*
|
* An authenticator which just delegates to a previous authenticator and issues *nice*
|
||||||
* error messages on failure to find credentials.
|
* error messages on failure to find credentials.
|
||||||
|
|
@ -80,7 +85,8 @@ object ErrorMessageAuthenticator {
|
||||||
* Since ivy installs its own credentials handler EVERY TIME it resolves or publishes, we want to
|
* Since ivy installs its own credentials handler EVERY TIME it resolves or publishes, we want to
|
||||||
* install this one at some point and eventually ivy will capture it and use it.
|
* install this one at some point and eventually ivy will capture it and use it.
|
||||||
*/
|
*/
|
||||||
private[sbt] final class ErrorMessageAuthenticator(original: Option[Authenticator]) extends Authenticator {
|
private[sbt] final class ErrorMessageAuthenticator(original: Option[Authenticator])
|
||||||
|
extends Authenticator {
|
||||||
|
|
||||||
protected override def getPasswordAuthentication(): PasswordAuthentication = {
|
protected override def getPasswordAuthentication(): PasswordAuthentication = {
|
||||||
// We're guaranteed to only get here if Ivy's authentication fails
|
// We're guaranteed to only get here if Ivy's authentication fails
|
||||||
|
|
@ -104,14 +110,16 @@ 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(Authenticator.requestPasswordAuthentication(
|
try 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
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@ import collection.JavaConverters._
|
||||||
|
|
||||||
/** A key used to store credentials in the ivy credentials store. */
|
/** A key used to store credentials in the ivy credentials store. */
|
||||||
private[sbt] sealed trait CredentialKey
|
private[sbt] sealed trait CredentialKey
|
||||||
|
|
||||||
/** Represents a key in the ivy credentials store that is only specific to a host. */
|
/** Represents a key in the ivy credentials store that is only specific to a host. */
|
||||||
private[sbt] case class Host(name: String) extends CredentialKey
|
private[sbt] case class Host(name: String) extends CredentialKey
|
||||||
|
|
||||||
/** Represents a key in the ivy credentials store that is keyed to both a host and a "realm". */
|
/** Represents a key in the ivy credentials store that is keyed to both a host and a "realm". */
|
||||||
private[sbt] case class Realm(host: String, realm: String) extends CredentialKey
|
private[sbt] case class Realm(host: String, realm: String) extends CredentialKey
|
||||||
|
|
||||||
|
|
@ -61,4 +63,4 @@ private[sbt] object IvyCredentialsLookup {
|
||||||
} mapValues { realms =>
|
} mapValues { realms =>
|
||||||
realms map (_.realm)
|
realms map (_.realm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,25 +13,25 @@ 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 =
|
|
||||||
{
|
|
||||||
assert(mergeable(a, b))
|
|
||||||
new MergedDescriptors(a, b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def apply(a: DependencyDescriptor, b: DependencyDescriptor): DependencyDescriptor = {
|
||||||
|
assert(mergeable(a, b))
|
||||||
|
new MergedDescriptors(a, b)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// combines the artifacts, configurations, includes, and excludes for DependencyDescriptors `a` and `b`
|
// combines the artifacts, configurations, includes, and excludes for DependencyDescriptors `a` and `b`
|
||||||
// that otherwise have equal IDs
|
// that otherwise have equal IDs
|
||||||
private[sbt] final case class MergedDescriptors(a: DependencyDescriptor, b: DependencyDescriptor) extends DependencyDescriptor {
|
private[sbt] final case class MergedDescriptors(a: DependencyDescriptor, b: DependencyDescriptor)
|
||||||
|
extends DependencyDescriptor {
|
||||||
def getDependencyId = a.getDependencyId
|
def getDependencyId = a.getDependencyId
|
||||||
def isForce = a.isForce
|
def isForce = a.isForce
|
||||||
def isChanging = a.isChanging
|
def isChanging = a.isChanging
|
||||||
|
|
@ -44,21 +44,41 @@ private[sbt] final case class MergedDescriptors(a: DependencyDescriptor, b: Depe
|
||||||
def getModuleConfigurations = concat(a.getModuleConfigurations, b.getModuleConfigurations)
|
def getModuleConfigurations = concat(a.getModuleConfigurations, b.getModuleConfigurations)
|
||||||
|
|
||||||
def getDependencyConfigurations(moduleConfiguration: String, requestedConfiguration: String) =
|
def getDependencyConfigurations(moduleConfiguration: String, requestedConfiguration: String) =
|
||||||
concat(a.getDependencyConfigurations(moduleConfiguration, requestedConfiguration), b.getDependencyConfigurations(moduleConfiguration))
|
concat(
|
||||||
|
a.getDependencyConfigurations(moduleConfiguration, requestedConfiguration),
|
||||||
|
b.getDependencyConfigurations(moduleConfiguration)
|
||||||
|
)
|
||||||
|
|
||||||
def getDependencyConfigurations(moduleConfiguration: String) =
|
def getDependencyConfigurations(moduleConfiguration: String) =
|
||||||
concat(a.getDependencyConfigurations(moduleConfiguration), b.getDependencyConfigurations(moduleConfiguration))
|
concat(
|
||||||
|
a.getDependencyConfigurations(moduleConfiguration),
|
||||||
|
b.getDependencyConfigurations(moduleConfiguration)
|
||||||
|
)
|
||||||
|
|
||||||
def getDependencyConfigurations(moduleConfigurations: Array[String]) =
|
def getDependencyConfigurations(moduleConfigurations: Array[String]) =
|
||||||
concat(a.getDependencyConfigurations(moduleConfigurations), b.getDependencyConfigurations(moduleConfigurations))
|
concat(
|
||||||
|
a.getDependencyConfigurations(moduleConfigurations),
|
||||||
|
b.getDependencyConfigurations(moduleConfigurations)
|
||||||
|
)
|
||||||
|
|
||||||
def getAllDependencyArtifacts = concatArtifacts(a, a.getAllDependencyArtifacts, b, b.getAllDependencyArtifacts)
|
def getAllDependencyArtifacts =
|
||||||
|
concatArtifacts(a, a.getAllDependencyArtifacts, b, b.getAllDependencyArtifacts)
|
||||||
|
|
||||||
def getDependencyArtifacts(moduleConfigurations: String) =
|
def getDependencyArtifacts(moduleConfigurations: String) =
|
||||||
concatArtifacts(a, a.getDependencyArtifacts(moduleConfigurations), b, b.getDependencyArtifacts(moduleConfigurations))
|
concatArtifacts(
|
||||||
|
a,
|
||||||
|
a.getDependencyArtifacts(moduleConfigurations),
|
||||||
|
b,
|
||||||
|
b.getDependencyArtifacts(moduleConfigurations)
|
||||||
|
)
|
||||||
|
|
||||||
def getDependencyArtifacts(moduleConfigurations: Array[String]) =
|
def getDependencyArtifacts(moduleConfigurations: Array[String]) =
|
||||||
concatArtifacts(a, a.getDependencyArtifacts(moduleConfigurations), b, b.getDependencyArtifacts(moduleConfigurations))
|
concatArtifacts(
|
||||||
|
a,
|
||||||
|
a.getDependencyArtifacts(moduleConfigurations),
|
||||||
|
b,
|
||||||
|
b.getDependencyArtifacts(moduleConfigurations)
|
||||||
|
)
|
||||||
|
|
||||||
def getAllIncludeRules = concat(a.getAllIncludeRules, b.getAllIncludeRules)
|
def getAllIncludeRules = concat(a.getAllIncludeRules, b.getAllIncludeRules)
|
||||||
|
|
||||||
|
|
@ -68,61 +88,99 @@ private[sbt] final case class MergedDescriptors(a: DependencyDescriptor, b: Depe
|
||||||
def getIncludeRules(moduleConfigurations: Array[String]) =
|
def getIncludeRules(moduleConfigurations: Array[String]) =
|
||||||
concat(a.getIncludeRules(moduleConfigurations), b.getIncludeRules(moduleConfigurations))
|
concat(a.getIncludeRules(moduleConfigurations), b.getIncludeRules(moduleConfigurations))
|
||||||
|
|
||||||
private[this] def concatArtifacts(a: DependencyDescriptor, as: Array[DependencyArtifactDescriptor], b: DependencyDescriptor, bs: Array[DependencyArtifactDescriptor]) =
|
private[this] def concatArtifacts(
|
||||||
{
|
a: DependencyDescriptor,
|
||||||
if (as.isEmpty)
|
as: Array[DependencyArtifactDescriptor],
|
||||||
if (bs.isEmpty) as
|
b: DependencyDescriptor,
|
||||||
else defaultArtifact(a) ++ explicitConfigurations(b, bs)
|
bs: Array[DependencyArtifactDescriptor]
|
||||||
else if (bs.isEmpty) explicitConfigurations(a, as) ++ defaultArtifact(b)
|
) = {
|
||||||
else concat(explicitConfigurations(a, as), explicitConfigurations(b, bs))
|
if (as.isEmpty)
|
||||||
|
if (bs.isEmpty) as
|
||||||
|
else defaultArtifact(a) ++ explicitConfigurations(b, bs)
|
||||||
|
else if (bs.isEmpty) explicitConfigurations(a, as) ++ defaultArtifact(b)
|
||||||
|
else concat(explicitConfigurations(a, as), explicitConfigurations(b, bs))
|
||||||
|
}
|
||||||
|
private[this] def explicitConfigurations(
|
||||||
|
base: DependencyDescriptor,
|
||||||
|
arts: Array[DependencyArtifactDescriptor]
|
||||||
|
): Array[DependencyArtifactDescriptor] =
|
||||||
|
arts map { art =>
|
||||||
|
explicitConfigurations(base, art)
|
||||||
}
|
}
|
||||||
private[this] def explicitConfigurations(base: DependencyDescriptor, arts: Array[DependencyArtifactDescriptor]): Array[DependencyArtifactDescriptor] =
|
private[this] def explicitConfigurations(
|
||||||
arts map { art => explicitConfigurations(base, art) }
|
base: DependencyDescriptor,
|
||||||
private[this] def explicitConfigurations(base: DependencyDescriptor, art: DependencyArtifactDescriptor): DependencyArtifactDescriptor =
|
art: DependencyArtifactDescriptor
|
||||||
{
|
): DependencyArtifactDescriptor = {
|
||||||
val aConfs = Option(art.getConfigurations) map { _.toList }
|
val aConfs = Option(art.getConfigurations) map { _.toList }
|
||||||
// In case configuration list is "*", we should still specify the module configuration of the DependencyDescriptor
|
// In case configuration list is "*", we should still specify the module configuration of the DependencyDescriptor
|
||||||
// otherwise the explicit specified artifacts from one dd can leak over to the other.
|
// otherwise the explicit specified artifacts from one dd can leak over to the other.
|
||||||
// See gh-1500, gh-2002
|
// See gh-1500, gh-2002
|
||||||
aConfs match {
|
aConfs match {
|
||||||
case None | Some(Nil) | Some(List("*")) => copyWithConfigurations(art, base.getModuleConfigurations)
|
case None | Some(Nil) | Some(List("*")) =>
|
||||||
case _ => art
|
copyWithConfigurations(art, base.getModuleConfigurations)
|
||||||
}
|
case _ => art
|
||||||
}
|
}
|
||||||
private[this] def defaultArtifact(a: DependencyDescriptor): Array[DependencyArtifactDescriptor] =
|
}
|
||||||
{
|
private[this] def defaultArtifact(a: DependencyDescriptor): Array[DependencyArtifactDescriptor] = {
|
||||||
val dd = new DefaultDependencyArtifactDescriptor(a, a.getDependencyRevisionId.getName, "jar", "jar", null, null)
|
val dd = new DefaultDependencyArtifactDescriptor(
|
||||||
addConfigurations(dd, a.getModuleConfigurations)
|
a,
|
||||||
// If the dependency descriptor is empty, then it means that it has been created from a POM file. In this case,
|
a.getDependencyRevisionId.getName,
|
||||||
// it is correct to create a seemingly non-existent dependency artifact.
|
"jar",
|
||||||
if (a.getAllDependencyArtifacts.isEmpty) Array(dd)
|
"jar",
|
||||||
else a.getAllDependencyArtifacts filter (_ == dd)
|
null,
|
||||||
}
|
null
|
||||||
private[this] def copyWithConfigurations(dd: DependencyArtifactDescriptor, confs: Seq[String]): DependencyArtifactDescriptor =
|
)
|
||||||
{
|
addConfigurations(dd, a.getModuleConfigurations)
|
||||||
val dextra = dd.getQualifiedExtraAttributes
|
// If the dependency descriptor is empty, then it means that it has been created from a POM file. In this case,
|
||||||
val newd = new DefaultDependencyArtifactDescriptor(dd.getDependencyDescriptor, dd.getName, dd.getType, dd.getExt, dd.getUrl, dextra)
|
// it is correct to create a seemingly non-existent dependency artifact.
|
||||||
addConfigurations(newd, confs)
|
if (a.getAllDependencyArtifacts.isEmpty) Array(dd)
|
||||||
newd
|
else a.getAllDependencyArtifacts filter (_ == dd)
|
||||||
}
|
}
|
||||||
private[this] def addConfigurations(dd: DefaultDependencyArtifactDescriptor, confs: Seq[String]): Unit =
|
private[this] def copyWithConfigurations(
|
||||||
|
dd: DependencyArtifactDescriptor,
|
||||||
|
confs: Seq[String]
|
||||||
|
): DependencyArtifactDescriptor = {
|
||||||
|
val dextra = dd.getQualifiedExtraAttributes
|
||||||
|
val newd = new DefaultDependencyArtifactDescriptor(
|
||||||
|
dd.getDependencyDescriptor,
|
||||||
|
dd.getName,
|
||||||
|
dd.getType,
|
||||||
|
dd.getExt,
|
||||||
|
dd.getUrl,
|
||||||
|
dextra
|
||||||
|
)
|
||||||
|
addConfigurations(newd, confs)
|
||||||
|
newd
|
||||||
|
}
|
||||||
|
private[this] def addConfigurations(
|
||||||
|
dd: DefaultDependencyArtifactDescriptor,
|
||||||
|
confs: Seq[String]
|
||||||
|
): Unit =
|
||||||
confs foreach dd.addConfiguration
|
confs foreach dd.addConfiguration
|
||||||
|
|
||||||
private[this] def concat[T: reflect.ClassTag](a: Array[T], b: Array[T]): Array[T] = (a ++ b).distinct
|
private[this] def concat[T: reflect.ClassTag](a: Array[T], b: Array[T]): Array[T] =
|
||||||
|
(a ++ b).distinct
|
||||||
|
|
||||||
def getAllExcludeRules = concat(a.getAllExcludeRules, b.getAllExcludeRules)
|
def getAllExcludeRules = concat(a.getAllExcludeRules, b.getAllExcludeRules)
|
||||||
|
|
||||||
def getExcludeRules(moduleConfigurations: String) = concat(a.getExcludeRules(moduleConfigurations), b.getExcludeRules(moduleConfigurations))
|
def getExcludeRules(moduleConfigurations: String) =
|
||||||
|
concat(a.getExcludeRules(moduleConfigurations), b.getExcludeRules(moduleConfigurations))
|
||||||
|
|
||||||
def getExcludeRules(moduleConfigurations: Array[String]) = concat(a.getExcludeRules(moduleConfigurations), b.getExcludeRules(moduleConfigurations))
|
def getExcludeRules(moduleConfigurations: Array[String]) =
|
||||||
|
concat(a.getExcludeRules(moduleConfigurations), b.getExcludeRules(moduleConfigurations))
|
||||||
|
|
||||||
def doesExclude(moduleConfigurations: Array[String], artifactId: ArtifactId) = a.doesExclude(moduleConfigurations, artifactId) || b.doesExclude(moduleConfigurations, artifactId)
|
def doesExclude(moduleConfigurations: Array[String], artifactId: ArtifactId) =
|
||||||
|
a.doesExclude(moduleConfigurations, artifactId) || b.doesExclude(
|
||||||
|
moduleConfigurations,
|
||||||
|
artifactId
|
||||||
|
)
|
||||||
|
|
||||||
def canExclude = a.canExclude || b.canExclude
|
def canExclude = a.canExclude || b.canExclude
|
||||||
|
|
||||||
def asSystem = this
|
def asSystem = this
|
||||||
|
|
||||||
def clone(revision: ModuleRevisionId) = new MergedDescriptors(a.clone(revision), b.clone(revision))
|
def clone(revision: ModuleRevisionId) =
|
||||||
|
new MergedDescriptors(a.clone(revision), b.clone(revision))
|
||||||
|
|
||||||
def getAttribute(name: String): String = a.getAttribute(name)
|
def getAttribute(name: String): String = a.getAttribute(name)
|
||||||
def getAttributes = a.getAttributes
|
def getAttributes = a.getAttributes
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,12 @@ import java.util.Date
|
||||||
|
|
||||||
import org.apache.ivy.core.settings.IvySettings
|
import org.apache.ivy.core.settings.IvySettings
|
||||||
import org.apache.ivy.core.{ IvyContext, LogOptions }
|
import org.apache.ivy.core.{ IvyContext, LogOptions }
|
||||||
import org.apache.ivy.core.module.descriptor.{ Artifact => IArtifact, DefaultModuleDescriptor, ModuleDescriptor, DependencyDescriptor }
|
import org.apache.ivy.core.module.descriptor.{
|
||||||
|
Artifact => IArtifact,
|
||||||
|
DefaultModuleDescriptor,
|
||||||
|
ModuleDescriptor,
|
||||||
|
DependencyDescriptor
|
||||||
|
}
|
||||||
import org.apache.ivy.core.resolve.{ ResolvedModuleRevision, ResolveData }
|
import org.apache.ivy.core.resolve.{ ResolvedModuleRevision, ResolveData }
|
||||||
import org.apache.ivy.plugins.latest.LatestStrategy
|
import org.apache.ivy.plugins.latest.LatestStrategy
|
||||||
import org.apache.ivy.plugins.repository.file.{ FileRepository => IFileRepository, FileResource }
|
import org.apache.ivy.plugins.repository.file.{ FileRepository => IFileRepository, FileResource }
|
||||||
|
|
@ -19,11 +24,11 @@ import sbt.util.Logger
|
||||||
import sbt.librarymanagement._
|
import sbt.librarymanagement._
|
||||||
|
|
||||||
private[sbt] case class SbtChainResolver(
|
private[sbt] case class SbtChainResolver(
|
||||||
name: String,
|
name: String,
|
||||||
resolvers: Seq[DependencyResolver],
|
resolvers: Seq[DependencyResolver],
|
||||||
settings: IvySettings,
|
settings: IvySettings,
|
||||||
updateOptions: UpdateOptions,
|
updateOptions: UpdateOptions,
|
||||||
log: Logger
|
log: Logger
|
||||||
) extends ChainResolver {
|
) extends ChainResolver {
|
||||||
|
|
||||||
override def equals(o: Any): Boolean = o match {
|
override def equals(o: Any): Boolean = o match {
|
||||||
|
|
@ -35,15 +40,14 @@ private[sbt] case class SbtChainResolver(
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
override def hashCode: Int =
|
override def hashCode: Int = {
|
||||||
{
|
var hash = 1
|
||||||
var hash = 1
|
hash = hash * 31 + this.name.##
|
||||||
hash = hash * 31 + this.name.##
|
hash = hash * 31 + this.resolvers.##
|
||||||
hash = hash * 31 + this.resolvers.##
|
hash = hash * 31 + this.settings.##
|
||||||
hash = hash * 31 + this.settings.##
|
hash = hash * 31 + this.updateOptions.##
|
||||||
hash = hash * 31 + this.updateOptions.##
|
hash
|
||||||
hash
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - We need to special case the project resolver so it always "wins" when resolving with inter-project dependencies.
|
// TODO - We need to special case the project resolver so it always "wins" when resolving with inter-project dependencies.
|
||||||
|
|
||||||
|
|
@ -67,105 +71,119 @@ private[sbt] case class SbtChainResolver(
|
||||||
//
|
//
|
||||||
// Ideally this could just skip the lookup, but unfortunately several artifacts in practice do not follow the
|
// Ideally this could just skip the lookup, but unfortunately several artifacts in practice do not follow the
|
||||||
// correct behavior for packaging="pom" and so it is only skipped for source/javadoc classifiers.
|
// correct behavior for packaging="pom" and so it is only skipped for source/javadoc classifiers.
|
||||||
override def locate(artifact: IArtifact) = if (IvySbt.hasImplicitClassifier(artifact)) null else super.locate(artifact)
|
override def locate(artifact: IArtifact) =
|
||||||
|
if (IvySbt.hasImplicitClassifier(artifact)) null else super.locate(artifact)
|
||||||
|
|
||||||
override def getDependency(dd: DependencyDescriptor, data: ResolveData) =
|
override def getDependency(dd: DependencyDescriptor, data: ResolveData) = {
|
||||||
{
|
if (data.getOptions.getLog != LogOptions.LOG_QUIET)
|
||||||
if (data.getOptions.getLog != LogOptions.LOG_QUIET)
|
Message.debug("Resolving " + dd.getDependencyRevisionId + " ...")
|
||||||
Message.debug("Resolving " + dd.getDependencyRevisionId + " ...")
|
val gd = doGetDependency(dd, data)
|
||||||
val gd = doGetDependency(dd, data)
|
val mod = IvySbt.resetArtifactResolver(gd)
|
||||||
val mod = IvySbt.resetArtifactResolver(gd)
|
mod
|
||||||
mod
|
}
|
||||||
}
|
|
||||||
// Modified implementation of ChainResolver#getDependency.
|
// Modified implementation of ChainResolver#getDependency.
|
||||||
// When the dependency is changing, it will check all resolvers on the chain
|
// When the dependency is changing, it will check all resolvers on the chain
|
||||||
// regardless of what the "latest strategy" is set, and look for the published date
|
// regardless of what the "latest strategy" is set, and look for the published date
|
||||||
// or the module descriptor to sort them.
|
// or the module descriptor to sort them.
|
||||||
// This implementation also skips resolution if "return first" is set to true,
|
// This implementation also skips resolution if "return first" is set to true,
|
||||||
// and if a previously resolved or cached revision has been found.
|
// and if a previously resolved or cached revision has been found.
|
||||||
def doGetDependency(dd: DependencyDescriptor, data0: ResolveData): ResolvedModuleRevision =
|
def doGetDependency(dd: DependencyDescriptor, data0: ResolveData): ResolvedModuleRevision = {
|
||||||
{
|
// useLatest - Means we should always download the JARs from the internet, no matter what.
|
||||||
// useLatest - Means we should always download the JARs from the internet, no matter what.
|
// This will only be true *IF* the depenendency is dynamic/changing *and* latestSnapshots is true.
|
||||||
// This will only be true *IF* the depenendency is dynamic/changing *and* latestSnapshots is true.
|
// If you find multiple candidates,
|
||||||
// If you find multiple candidates,
|
// - If `isReturnFirst` is true, you return the first value found
|
||||||
// - If `isReturnFirst` is true, you return the first value found
|
// - If not, we will ATTEMPT to look at the publish date, which is not correctly discovered for Maven modules and
|
||||||
// - If not, we will ATTEMPT to look at the publish date, which is not correctly discovered for Maven modules and
|
// leads to undefined behavior.
|
||||||
// leads to undefined behavior.
|
val useLatest = (dd.isChanging || IvySbt.isChanging(dd.getDependencyRevisionId)) && updateOptions.latestSnapshots
|
||||||
val useLatest = (dd.isChanging || IvySbt.isChanging(dd.getDependencyRevisionId)) && updateOptions.latestSnapshots
|
if (useLatest) {
|
||||||
if (useLatest) {
|
Message.verbose(s"$getName is changing. Checking all resolvers on the chain")
|
||||||
Message.verbose(s"$getName is changing. Checking all resolvers on the chain")
|
}
|
||||||
}
|
val data = new ResolveData(data0, doValidate(data0))
|
||||||
val data = new ResolveData(data0, doValidate(data0))
|
// Returns the value if we've already been resolved from some other branch of the resolution tree.
|
||||||
// Returns the value if we've already been resolved from some other branch of the resolution tree.
|
val resolved = Option(data.getCurrentResolvedModuleRevision)
|
||||||
val resolved = Option(data.getCurrentResolvedModuleRevision)
|
// If we don't have any previously resolved date, we try to pull the value from the cache.
|
||||||
// If we don't have any previously resolved date, we try to pull the value from the cache.
|
val resolvedOrCached =
|
||||||
val resolvedOrCached =
|
resolved orElse {
|
||||||
resolved orElse {
|
Message.verbose(getName + ": Checking cache for: " + dd)
|
||||||
Message.verbose(getName + ": Checking cache for: " + dd)
|
Option(findModuleInCache(dd, data, true)) map { mr =>
|
||||||
Option(findModuleInCache(dd, data, true)) map { mr =>
|
Message.verbose(getName + ": module revision found in cache: " + mr.getId)
|
||||||
Message.verbose(getName + ": module revision found in cache: " + mr.getId)
|
forcedRevision(mr)
|
||||||
forcedRevision(mr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Default value for resolution. We use this while we loop...
|
// Default value for resolution. We use this while we loop...
|
||||||
// If useLatest is true, we want to try to download from the internet so we DO NOT start with a valid value.
|
// If useLatest is true, we want to try to download from the internet so we DO NOT start with a valid value.
|
||||||
var temp: Option[ResolvedModuleRevision] =
|
var temp: Option[ResolvedModuleRevision] =
|
||||||
if (useLatest) None
|
if (useLatest) None
|
||||||
else resolvedOrCached
|
else resolvedOrCached
|
||||||
// Cast resolvers to something useful. TODO - we dropping anything here?
|
// Cast resolvers to something useful. TODO - we dropping anything here?
|
||||||
val resolvers = getResolvers.toArray.toVector collect { case x: DependencyResolver => x }
|
val resolvers = getResolvers.toArray.toVector collect { case x: DependencyResolver => x }
|
||||||
val interProjResolver = resolvers find { x => x.getName == ProjectResolver.InterProject }
|
val interProjResolver = resolvers find { x =>
|
||||||
|
x.getName == ProjectResolver.InterProject
|
||||||
|
}
|
||||||
|
|
||||||
// Here we do an attempt to resolve the artifact from each of the resolvers in the chain.
|
// Here we do an attempt to resolve the artifact from each of the resolvers in the chain.
|
||||||
// - If we have a return value already, AND isReturnFirst is true AND useLatest is false, we DO NOT resolve anything
|
// - If we have a return value already, AND isReturnFirst is true AND useLatest is false, we DO NOT resolve anything
|
||||||
// - If we do not, try to resolve.
|
// - If we do not, try to resolve.
|
||||||
// RETURNS: Left -> Error
|
// RETURNS: Left -> Error
|
||||||
// Right -> Some(resolved module) // Found in this resolver, can use this result.
|
// Right -> Some(resolved module) // Found in this resolver, can use this result.
|
||||||
// Right -> None // Do not use this resolver
|
// Right -> None // Do not use this resolver
|
||||||
lazy val results = resolvers map { x =>
|
lazy val results = resolvers map { x =>
|
||||||
// if the revision is cached and isReturnFirst is set, don't bother hitting any resolvers, just return None for this guy.
|
// if the revision is cached and isReturnFirst is set, don't bother hitting any resolvers, just return None for this guy.
|
||||||
if (isReturnFirst && temp.isDefined && !useLatest) Right(None)
|
if (isReturnFirst && temp.isDefined && !useLatest) Right(None)
|
||||||
else {
|
else {
|
||||||
// We actually do resolution.
|
// We actually do resolution.
|
||||||
val resolver = x
|
val resolver = x
|
||||||
val oldLatest: Option[LatestStrategy] = setLatestIfRequired(resolver, Option(getLatestStrategy))
|
val oldLatest: Option[LatestStrategy] =
|
||||||
try {
|
setLatestIfRequired(resolver, Option(getLatestStrategy))
|
||||||
val previouslyResolved = temp
|
try {
|
||||||
// if the module qualifies as changing, then resolve all resolvers
|
val previouslyResolved = temp
|
||||||
if (useLatest) data.setCurrentResolvedModuleRevision(null)
|
// if the module qualifies as changing, then resolve all resolvers
|
||||||
else data.setCurrentResolvedModuleRevision(temp.orNull)
|
if (useLatest) data.setCurrentResolvedModuleRevision(null)
|
||||||
temp = Option(resolver.getDependency(dd, data))
|
else data.setCurrentResolvedModuleRevision(temp.orNull)
|
||||||
Right(
|
temp = Option(resolver.getDependency(dd, data))
|
||||||
if (temp eq previouslyResolved) None
|
Right(
|
||||||
else if (useLatest) temp map { x =>
|
if (temp eq previouslyResolved) None
|
||||||
(reparseModuleDescriptor(dd, data, resolver, x), resolver)
|
else if (useLatest) temp map { x =>
|
||||||
|
(reparseModuleDescriptor(dd, data, resolver, x), resolver)
|
||||||
|
} else
|
||||||
|
temp map { x =>
|
||||||
|
(forcedRevision(x), resolver)
|
||||||
}
|
}
|
||||||
else temp map { x => (forcedRevision(x), resolver) }
|
)
|
||||||
|
} catch {
|
||||||
|
case ex: Exception =>
|
||||||
|
Message.verbose(
|
||||||
|
"problem occurred while resolving " + dd + " with " + resolver
|
||||||
|
+ ": " + IvyStringUtils.getStackTrace(ex)
|
||||||
)
|
)
|
||||||
} catch {
|
Left(ex)
|
||||||
case ex: Exception =>
|
} finally {
|
||||||
Message.verbose("problem occurred while resolving " + dd + " with " + resolver
|
oldLatest map { _ =>
|
||||||
+ ": " + IvyStringUtils.getStackTrace(ex))
|
doSetLatestStrategy(resolver, oldLatest)
|
||||||
Left(ex)
|
|
||||||
} finally {
|
|
||||||
oldLatest map { _ => doSetLatestStrategy(resolver, oldLatest) }
|
|
||||||
checkInterrupted()
|
|
||||||
}
|
}
|
||||||
|
checkInterrupted()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lazy val errors = results collect { case Left(e) => e }
|
}
|
||||||
|
lazy val errors = results collect { case Left(e) => e }
|
||||||
|
|
||||||
// If the value is arleady in cache, SORTED will be a Seq(None, None, ...) which means we'll fall over to the prevously cached or resolved version.
|
// If the value is arleady in cache, SORTED will be a Seq(None, None, ...) which means we'll fall over to the prevously cached or resolved version.
|
||||||
val mrOpt: Option[ResolvedModuleRevision] = {
|
val mrOpt: Option[ResolvedModuleRevision] = {
|
||||||
val interProj: Option[ResolvedModuleRevision] =
|
val interProj: Option[ResolvedModuleRevision] =
|
||||||
if (updateOptions.interProjectFirst) interProjResolver flatMap { x => Option(x.getDependency(dd, data)) }
|
if (updateOptions.interProjectFirst) interProjResolver flatMap { x =>
|
||||||
else None
|
Option(x.getDependency(dd, data))
|
||||||
def foundRevisions: Vector[(ResolvedModuleRevision, DependencyResolver)] = results collect { case Right(Some(x)) => x }
|
} else None
|
||||||
def sorted =
|
def foundRevisions: Vector[(ResolvedModuleRevision, DependencyResolver)] = results collect {
|
||||||
if (useLatest) (foundRevisions.sortBy {
|
case Right(Some(x)) => x
|
||||||
|
}
|
||||||
|
def sorted =
|
||||||
|
if (useLatest)(foundRevisions
|
||||||
|
.sortBy {
|
||||||
case (rmr, resolver) =>
|
case (rmr, resolver) =>
|
||||||
Message.warn(s"Sorting results from $rmr, using ${rmr.getPublicationDate} and ${rmr.getDescriptor.getPublicationDate}")
|
Message.warn(
|
||||||
|
s"Sorting results from $rmr, using ${rmr.getPublicationDate} and ${rmr.getDescriptor.getPublicationDate}"
|
||||||
|
)
|
||||||
// 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.
|
||||||
Option(rmr.getPublicationDate) orElse Option(rmr.getDescriptor.getPublicationDate) match {
|
Option(rmr.getPublicationDate) orElse Option(rmr.getDescriptor.getPublicationDate) match {
|
||||||
case None =>
|
case None =>
|
||||||
|
|
@ -173,55 +191,75 @@ private[sbt] case class SbtChainResolver(
|
||||||
case (null, _) =>
|
case (null, _) =>
|
||||||
// In this instance, the dependency is specified by a direct URL or some other sort of "non-ivy" file
|
// In this instance, the dependency is specified by a direct URL or some other sort of "non-ivy" file
|
||||||
if (dd.isChanging)
|
if (dd.isChanging)
|
||||||
Message.warn(s"Resolving a changing dependency (${rmr.getId}) with no ivy/pom file!, resolution order is undefined!")
|
Message.warn(
|
||||||
|
s"Resolving a changing dependency (${rmr.getId}) with no ivy/pom file!, resolution order is undefined!"
|
||||||
|
)
|
||||||
0L
|
0L
|
||||||
case (ivf, dmd: DefaultModuleDescriptor) =>
|
case (ivf, dmd: DefaultModuleDescriptor) =>
|
||||||
val lmd = new java.util.Date(ivf.getLastModified)
|
val lmd = new java.util.Date(ivf.getLastModified)
|
||||||
Message.debug(s"Getting no publication date from resolver: ${resolver} for ${rmr.getId}, setting to: ${lmd}")
|
Message.debug(
|
||||||
|
s"Getting no publication date from resolver: ${resolver} for ${rmr.getId}, setting to: ${lmd}"
|
||||||
|
)
|
||||||
dmd.setPublicationDate(lmd)
|
dmd.setPublicationDate(lmd)
|
||||||
ivf.getLastModified
|
ivf.getLastModified
|
||||||
case _ =>
|
case _ =>
|
||||||
Message.warn(s"Getting null publication date from resolver: ${resolver} for ${rmr.getId}, resolution order is undefined!")
|
Message.warn(
|
||||||
|
s"Getting null publication date from resolver: ${resolver} for ${rmr.getId}, resolution order is undefined!"
|
||||||
|
)
|
||||||
0L
|
0L
|
||||||
}
|
}
|
||||||
case Some(date) => // All other cases ok
|
case Some(date) => // All other cases ok
|
||||||
date.getTime
|
date.getTime
|
||||||
}
|
}
|
||||||
}).reverse.headOption map {
|
})
|
||||||
case (rmr, resolver) =>
|
.reverse
|
||||||
Message.warn(s"Choosing $resolver for ${rmr.getId}")
|
.headOption map {
|
||||||
// Now that we know the real latest revision, let's force Ivy to use it
|
case (rmr, resolver) =>
|
||||||
val artifactOpt = findFirstArtifactRef(rmr.getDescriptor, dd, data, resolver)
|
Message.warn(s"Choosing $resolver for ${rmr.getId}")
|
||||||
artifactOpt match {
|
// Now that we know the real latest revision, let's force Ivy to use it
|
||||||
case Some(artifactRef) =>
|
val artifactOpt = findFirstArtifactRef(rmr.getDescriptor, dd, data, resolver)
|
||||||
val systemMd = toSystem(rmr.getDescriptor)
|
artifactOpt match {
|
||||||
getRepositoryCacheManager.cacheModuleDescriptor(resolver, artifactRef,
|
case Some(artifactRef) =>
|
||||||
toSystem(dd), systemMd.getAllArtifacts.head, None.orNull, getCacheOptions(data))
|
val systemMd = toSystem(rmr.getDescriptor)
|
||||||
case None => // do nothing. There are modules without artifacts
|
getRepositoryCacheManager.cacheModuleDescriptor(
|
||||||
}
|
resolver,
|
||||||
rmr
|
artifactRef,
|
||||||
}
|
toSystem(dd),
|
||||||
else foundRevisions.reverse.headOption map { _._1 } // we have to reverse because resolvers are hit in reverse order.
|
systemMd.getAllArtifacts.head,
|
||||||
|
None.orNull,
|
||||||
|
getCacheOptions(data)
|
||||||
|
)
|
||||||
|
case None => // do nothing. There are modules without artifacts
|
||||||
|
}
|
||||||
|
rmr
|
||||||
|
} else
|
||||||
|
foundRevisions.reverse.headOption map { _._1 } // we have to reverse because resolvers are hit in reverse order.
|
||||||
|
|
||||||
interProj orElse sorted orElse resolvedOrCached
|
interProj orElse sorted orElse resolvedOrCached
|
||||||
}
|
|
||||||
mrOpt match {
|
|
||||||
case None if errors.size == 1 =>
|
|
||||||
errors.head match {
|
|
||||||
case e: RuntimeException => throw e
|
|
||||||
case e: ParseException => throw e
|
|
||||||
case e: Throwable => throw new RuntimeException(e.toString, e)
|
|
||||||
}
|
|
||||||
case None if errors.size > 1 =>
|
|
||||||
val err = (errors.toList map { IvyStringUtils.getErrorMessage }).mkString("\n\t", "\n\t", "\n")
|
|
||||||
throw new RuntimeException(s"several problems occurred while resolving $dd:$err")
|
|
||||||
case _ =>
|
|
||||||
if (resolved == mrOpt) resolved.orNull
|
|
||||||
else (mrOpt map { resolvedRevision }).orNull
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
mrOpt match {
|
||||||
|
case None if errors.size == 1 =>
|
||||||
|
errors.head match {
|
||||||
|
case e: RuntimeException => throw e
|
||||||
|
case e: ParseException => throw e
|
||||||
|
case e: Throwable => throw new RuntimeException(e.toString, e)
|
||||||
|
}
|
||||||
|
case None if errors.size > 1 =>
|
||||||
|
val err =
|
||||||
|
(errors.toList map { IvyStringUtils.getErrorMessage }).mkString("\n\t", "\n\t", "\n")
|
||||||
|
throw new RuntimeException(s"several problems occurred while resolving $dd:$err")
|
||||||
|
case _ =>
|
||||||
|
if (resolved == mrOpt) resolved.orNull
|
||||||
|
else (mrOpt map { resolvedRevision }).orNull
|
||||||
|
}
|
||||||
|
}
|
||||||
// Ivy seem to not want to use the module descriptor found at the latest resolver
|
// Ivy seem to not want to use the module descriptor found at the latest resolver
|
||||||
private[this] def reparseModuleDescriptor(dd: DependencyDescriptor, data: ResolveData, resolver: DependencyResolver, rmr: ResolvedModuleRevision): ResolvedModuleRevision =
|
private[this] def reparseModuleDescriptor(
|
||||||
|
dd: DependencyDescriptor,
|
||||||
|
data: ResolveData,
|
||||||
|
resolver: DependencyResolver,
|
||||||
|
rmr: ResolvedModuleRevision
|
||||||
|
): ResolvedModuleRevision =
|
||||||
// TODO - Redownloading/parsing the ivy file is not really the best way to make this correct.
|
// TODO - Redownloading/parsing the ivy file is not really the best way to make this correct.
|
||||||
// We should figure out a better alternative, or directly attack the resolvers Ivy uses to
|
// We should figure out a better alternative, or directly attack the resolvers Ivy uses to
|
||||||
// give them correct behavior around -SNAPSHOT.
|
// give them correct behavior around -SNAPSHOT.
|
||||||
|
|
@ -238,49 +276,76 @@ private[sbt] case class SbtChainResolver(
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
}
|
||||||
} getOrElse {
|
} getOrElse {
|
||||||
Message.warn(s"Unable to reparse ${dd.getDependencyRevisionId} from $resolver, using ${rmr.getPublicationDate}")
|
Message.warn(
|
||||||
|
s"Unable to reparse ${dd.getDependencyRevisionId} from $resolver, using ${rmr.getPublicationDate}"
|
||||||
|
)
|
||||||
rmr
|
rmr
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ported from BasicResolver#findFirstAirfactRef. */
|
/** Ported from BasicResolver#findFirstAirfactRef. */
|
||||||
private[this] def findFirstArtifactRef(md: ModuleDescriptor, dd: DependencyDescriptor, data: ResolveData, resolver: DependencyResolver): Option[ResolvedResource] =
|
private[this] def findFirstArtifactRef(
|
||||||
{
|
md: ModuleDescriptor,
|
||||||
def artifactRef(artifact: IArtifact, date: Date): Option[ResolvedResource] =
|
dd: DependencyDescriptor,
|
||||||
resolver match {
|
data: ResolveData,
|
||||||
case resolver: BasicResolver =>
|
resolver: DependencyResolver
|
||||||
IvyContext.getContext.set(resolver.getName + ".artifact", artifact)
|
): Option[ResolvedResource] = {
|
||||||
try {
|
def artifactRef(artifact: IArtifact, date: Date): Option[ResolvedResource] =
|
||||||
Option(resolver.doFindArtifactRef(artifact, date)) orElse {
|
resolver match {
|
||||||
Option(artifact.getUrl) map { url =>
|
case resolver: BasicResolver =>
|
||||||
Message.verbose("\tusing url for " + artifact + ": " + url)
|
IvyContext.getContext.set(resolver.getName + ".artifact", artifact)
|
||||||
val resource =
|
try {
|
||||||
if ("file" == url.getProtocol) new FileResource(new IFileRepository(), new File(url.getPath))
|
Option(resolver.doFindArtifactRef(artifact, date)) orElse {
|
||||||
else new URLResource(url)
|
Option(artifact.getUrl) map { url =>
|
||||||
new ResolvedResource(resource, artifact.getModuleRevisionId.getRevision)
|
Message.verbose("\tusing url for " + artifact + ": " + url)
|
||||||
}
|
val resource =
|
||||||
|
if ("file" == url.getProtocol)
|
||||||
|
new FileResource(new IFileRepository(), new File(url.getPath))
|
||||||
|
else new URLResource(url)
|
||||||
|
new ResolvedResource(resource, artifact.getModuleRevisionId.getRevision)
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
IvyContext.getContext.set(resolver.getName + ".artifact", null)
|
|
||||||
}
|
}
|
||||||
case _ =>
|
} finally {
|
||||||
None
|
IvyContext.getContext.set(resolver.getName + ".artifact", null)
|
||||||
}
|
}
|
||||||
val artifactRefs = md.getConfigurations.toIterator flatMap { conf =>
|
case _ =>
|
||||||
md.getArtifacts(conf.getName).toIterator flatMap { af =>
|
None
|
||||||
artifactRef(af, data.getDate).toIterator
|
}
|
||||||
}
|
val artifactRefs = md.getConfigurations.toIterator flatMap { conf =>
|
||||||
|
md.getArtifacts(conf.getName).toIterator flatMap { af =>
|
||||||
|
artifactRef(af, data.getDate).toIterator
|
||||||
}
|
}
|
||||||
if (artifactRefs.hasNext) Some(artifactRefs.next())
|
|
||||||
else None
|
|
||||||
}
|
}
|
||||||
|
if (artifactRefs.hasNext) Some(artifactRefs.next())
|
||||||
|
else None
|
||||||
|
}
|
||||||
|
|
||||||
/** Ported from ChainResolver#forcedRevision. */
|
/** Ported from ChainResolver#forcedRevision. */
|
||||||
private[this] def forcedRevision(rmr: ResolvedModuleRevision): ResolvedModuleRevision =
|
private[this] def forcedRevision(rmr: ResolvedModuleRevision): ResolvedModuleRevision =
|
||||||
new ResolvedModuleRevision(rmr.getResolver, rmr.getArtifactResolver, rmr.getDescriptor, rmr.getReport, true)
|
new ResolvedModuleRevision(
|
||||||
|
rmr.getResolver,
|
||||||
|
rmr.getArtifactResolver,
|
||||||
|
rmr.getDescriptor,
|
||||||
|
rmr.getReport,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
/** Ported from ChainResolver#resolvedRevision. */
|
/** Ported from ChainResolver#resolvedRevision. */
|
||||||
private[this] def resolvedRevision(rmr: ResolvedModuleRevision): ResolvedModuleRevision =
|
private[this] def resolvedRevision(rmr: ResolvedModuleRevision): ResolvedModuleRevision =
|
||||||
if (isDual) new ResolvedModuleRevision(rmr.getResolver, this, rmr.getDescriptor, rmr.getReport, rmr.isForce)
|
if (isDual)
|
||||||
|
new ResolvedModuleRevision(
|
||||||
|
rmr.getResolver,
|
||||||
|
this,
|
||||||
|
rmr.getDescriptor,
|
||||||
|
rmr.getReport,
|
||||||
|
rmr.isForce
|
||||||
|
)
|
||||||
else rmr
|
else rmr
|
||||||
|
|
||||||
/** Ported from ChainResolver#setLatestIfRequired. */
|
/** Ported from ChainResolver#setLatestIfRequired. */
|
||||||
private[this] def setLatestIfRequired(resolver: DependencyResolver, latest: Option[LatestStrategy]): Option[LatestStrategy] =
|
private[this] def setLatestIfRequired(
|
||||||
|
resolver: DependencyResolver,
|
||||||
|
latest: Option[LatestStrategy]
|
||||||
|
): Option[LatestStrategy] =
|
||||||
latestStrategyName(resolver) match {
|
latestStrategyName(resolver) match {
|
||||||
case Some(latestName) if latestName != "default" =>
|
case Some(latestName) if latestName != "default" =>
|
||||||
val oldLatest = latestStrategy(resolver)
|
val oldLatest = latestStrategy(resolver)
|
||||||
|
|
@ -288,20 +353,26 @@ private[sbt] case class SbtChainResolver(
|
||||||
oldLatest
|
oldLatest
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ported from ChainResolver#getLatestStrategyName. */
|
/** Ported from ChainResolver#getLatestStrategyName. */
|
||||||
private[this] def latestStrategyName(resolver: DependencyResolver): Option[String] =
|
private[this] def latestStrategyName(resolver: DependencyResolver): Option[String] =
|
||||||
resolver match {
|
resolver match {
|
||||||
case r: HasLatestStrategy => Some(r.getLatest)
|
case r: HasLatestStrategy => Some(r.getLatest)
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ported from ChainResolver#getLatest. */
|
/** Ported from ChainResolver#getLatest. */
|
||||||
private[this] def latestStrategy(resolver: DependencyResolver): Option[LatestStrategy] =
|
private[this] def latestStrategy(resolver: DependencyResolver): Option[LatestStrategy] =
|
||||||
resolver match {
|
resolver match {
|
||||||
case r: HasLatestStrategy => Some(r.getLatestStrategy)
|
case r: HasLatestStrategy => Some(r.getLatestStrategy)
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ported from ChainResolver#setLatest. */
|
/** Ported from ChainResolver#setLatest. */
|
||||||
private[this] def doSetLatestStrategy(resolver: DependencyResolver, latest: Option[LatestStrategy]): Option[LatestStrategy] =
|
private[this] def doSetLatestStrategy(
|
||||||
|
resolver: DependencyResolver,
|
||||||
|
latest: Option[LatestStrategy]
|
||||||
|
): Option[LatestStrategy] =
|
||||||
resolver match {
|
resolver match {
|
||||||
case r: HasLatestStrategy =>
|
case r: HasLatestStrategy =>
|
||||||
val oldLatest = latestStrategy(resolver)
|
val oldLatest = latestStrategy(resolver)
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,16 @@ object PomExtraDependencyAttributes {
|
||||||
val ExtraAttributesKey = "extraDependencyAttributes"
|
val ExtraAttributesKey = "extraDependencyAttributes"
|
||||||
val SbtVersionKey = "sbtVersion"
|
val SbtVersionKey = "sbtVersion"
|
||||||
val ScalaVersionKey = "scalaVersion"
|
val ScalaVersionKey = "scalaVersion"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the extra dependency attributes out of a maven property.
|
* Reads the extra dependency attributes out of a maven property.
|
||||||
* @param props The properties from an Aether resolution.
|
* @param props The properties from an Aether resolution.
|
||||||
* @return
|
* @return
|
||||||
* A map of module id to extra dependency attributes associated with dependencies on that module.
|
* A map of module id to extra dependency attributes associated with dependencies on that module.
|
||||||
*/
|
*/
|
||||||
def readFromAether(props: java.util.Map[String, AnyRef]): Map[ModuleRevisionId, Map[String, String]] = {
|
def readFromAether(
|
||||||
|
props: java.util.Map[String, AnyRef]
|
||||||
|
): Map[ModuleRevisionId, Map[String, String]] = {
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
(props.asScala get ExtraAttributesKey) match {
|
(props.asScala get ExtraAttributesKey) match {
|
||||||
case None => Map.empty
|
case None => Map.empty
|
||||||
|
|
@ -52,7 +55,10 @@ object PomExtraDependencyAttributes {
|
||||||
* TODO - maybe we can just parse this directly here. Note the `readFromAether` method uses
|
* TODO - maybe we can just parse this directly here. Note the `readFromAether` method uses
|
||||||
* whatever we set here.
|
* whatever we set here.
|
||||||
*/
|
*/
|
||||||
def transferDependencyExtraAttributes(from: Properties, to: java.util.Map[String, AnyRef]): Unit =
|
def transferDependencyExtraAttributes(
|
||||||
|
from: Properties,
|
||||||
|
to: java.util.Map[String, AnyRef]
|
||||||
|
): Unit =
|
||||||
Option(from.getProperty(ExtraAttributesKey, null)) foreach (to.put(ExtraAttributesKey, _))
|
Option(from.getProperty(ExtraAttributesKey, null)) foreach (to.put(ExtraAttributesKey, _))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -72,16 +78,25 @@ object PomExtraDependencyAttributes {
|
||||||
item.getQualifiedExtraAttributes.asInstanceOf[java.util.Map[String, String]].asScala.toMap
|
item.getQualifiedExtraAttributes.asInstanceOf[java.util.Map[String, String]].asScala.toMap
|
||||||
}
|
}
|
||||||
def filterCustomExtra(item: ExtendableItem, include: Boolean): Map[String, String] =
|
def filterCustomExtra(item: ExtendableItem, include: Boolean): Map[String, String] =
|
||||||
(qualifiedExtra(item) filterKeys { k => qualifiedIsExtra(k) == include })
|
(qualifiedExtra(item) filterKeys { k =>
|
||||||
|
qualifiedIsExtra(k) == include
|
||||||
|
})
|
||||||
|
|
||||||
def qualifiedIsExtra(k: String): Boolean = k.endsWith(ScalaVersionKey) || k.endsWith(SbtVersionKey)
|
def qualifiedIsExtra(k: String): Boolean =
|
||||||
|
k.endsWith(ScalaVersionKey) || k.endsWith(SbtVersionKey)
|
||||||
|
|
||||||
// Reduces the id to exclude custom extra attributes
|
// Reduces the id to exclude custom extra attributes
|
||||||
// This makes the id suitable as a key to associate a dependency parsed from a <dependency> element
|
// This makes the id suitable as a key to associate a dependency parsed from a <dependency> element
|
||||||
// with the extra attributes from the <properties> section
|
// with the extra attributes from the <properties> section
|
||||||
def simplify(id: ModuleRevisionId): ModuleRevisionId = {
|
def simplify(id: ModuleRevisionId): ModuleRevisionId = {
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
ModuleRevisionId.newInstance(id.getOrganisation, id.getName, id.getBranch, id.getRevision, filterCustomExtra(id, include = false).asJava)
|
ModuleRevisionId.newInstance(
|
||||||
|
id.getOrganisation,
|
||||||
|
id.getName,
|
||||||
|
id.getBranch,
|
||||||
|
id.getRevision,
|
||||||
|
filterCustomExtra(id, include = false).asJava
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** parses the sequence of dependencies with extra attribute information, with one dependency per line */
|
/** parses the sequence of dependencies with extra attribute information, with one dependency per line */
|
||||||
|
|
|
||||||
|
|
@ -16,28 +16,48 @@ abstract class ArtifactExtra {
|
||||||
def extraAttributes: Map[String, String]
|
def extraAttributes: Map[String, String]
|
||||||
|
|
||||||
protected[this] def copy(
|
protected[this] def copy(
|
||||||
name: String = name,
|
name: String = name,
|
||||||
`type`: String = `type`,
|
`type`: String = `type`,
|
||||||
extension: String = extension,
|
extension: String = extension,
|
||||||
classifier: Option[String] = classifier,
|
classifier: Option[String] = classifier,
|
||||||
configurations: Vector[Configuration] = configurations,
|
configurations: Vector[Configuration] = configurations,
|
||||||
url: Option[URL] = url,
|
url: Option[URL] = url,
|
||||||
extraAttributes: Map[String, String] = extraAttributes
|
extraAttributes: Map[String, String] = extraAttributes
|
||||||
): Artifact
|
): Artifact
|
||||||
|
|
||||||
def extra(attributes: (String, String)*) = copy(extraAttributes = extraAttributes ++ ModuleID.checkE(attributes))
|
def extra(attributes: (String, String)*) =
|
||||||
|
copy(extraAttributes = extraAttributes ++ ModuleID.checkE(attributes))
|
||||||
}
|
}
|
||||||
|
|
||||||
import Configurations.{ Optional, Pom, Test }
|
import Configurations.{ Optional, Pom, Test }
|
||||||
|
|
||||||
abstract class ArtifactFunctions {
|
abstract class ArtifactFunctions {
|
||||||
def apply(name: String, extra: Map[String, String]): Artifact = Artifact(name, DefaultType, DefaultExtension, None, Vector.empty, None, extra)
|
def apply(name: String, extra: Map[String, String]): Artifact =
|
||||||
def apply(name: String, classifier: String): Artifact = Artifact(name, DefaultType, DefaultExtension, Some(classifier), Vector.empty, None)
|
Artifact(name, DefaultType, DefaultExtension, None, Vector.empty, None, extra)
|
||||||
def apply(name: String, `type`: String, extension: String): Artifact = Artifact(name, `type`, extension, None, Vector.empty, None)
|
def apply(name: String, classifier: String): Artifact =
|
||||||
def apply(name: String, `type`: String, extension: String, classifier: String): Artifact = Artifact(name, `type`, extension, Some(classifier), Vector.empty, None)
|
Artifact(name, DefaultType, DefaultExtension, Some(classifier), Vector.empty, None)
|
||||||
def apply(name: String, url: URL): Artifact = Artifact(name, extract(url, DefaultType), extract(url, DefaultExtension), None, Vector.empty, Some(url))
|
def apply(name: String, `type`: String, extension: String): Artifact =
|
||||||
|
Artifact(name, `type`, extension, None, Vector.empty, None)
|
||||||
|
def apply(name: String, `type`: String, extension: String, classifier: String): Artifact =
|
||||||
|
Artifact(name, `type`, extension, Some(classifier), Vector.empty, None)
|
||||||
|
def apply(name: String, url: URL): Artifact =
|
||||||
|
Artifact(
|
||||||
|
name,
|
||||||
|
extract(url, DefaultType),
|
||||||
|
extract(url, DefaultExtension),
|
||||||
|
None,
|
||||||
|
Vector.empty,
|
||||||
|
Some(url)
|
||||||
|
)
|
||||||
|
|
||||||
def apply(name: String, `type`: String, extension: String, classifier: Option[String], configurations: Vector[Configuration], url: Option[URL]): Artifact =
|
def apply(
|
||||||
|
name: String,
|
||||||
|
`type`: String,
|
||||||
|
extension: String,
|
||||||
|
classifier: Option[String],
|
||||||
|
configurations: Vector[Configuration],
|
||||||
|
url: Option[URL]
|
||||||
|
): Artifact =
|
||||||
Artifact(name, `type`, extension, classifier, configurations, url, Map.empty[String, String])
|
Artifact(name, `type`, extension, classifier, configurations, url, Map.empty[String, String])
|
||||||
|
|
||||||
val DefaultExtension = "jar"
|
val DefaultExtension = "jar"
|
||||||
|
|
@ -66,29 +86,33 @@ abstract class ArtifactFunctions {
|
||||||
assert(DefaultSourceTypes contains SourceType)
|
assert(DefaultSourceTypes contains SourceType)
|
||||||
|
|
||||||
def extract(url: URL, default: String): String = extract(url.toString, default)
|
def extract(url: URL, default: String): String = extract(url.toString, default)
|
||||||
def extract(name: String, default: String): String =
|
def extract(name: String, default: String): String = {
|
||||||
{
|
val i = name.lastIndexOf('.')
|
||||||
val i = name.lastIndexOf('.')
|
if (i >= 0)
|
||||||
if (i >= 0)
|
name.substring(i + 1)
|
||||||
name.substring(i + 1)
|
else
|
||||||
else
|
default
|
||||||
default
|
}
|
||||||
}
|
def defaultArtifact(file: File) = {
|
||||||
def defaultArtifact(file: File) =
|
val name = file.getName
|
||||||
{
|
val i = name.lastIndexOf('.')
|
||||||
val name = file.getName
|
val base = if (i >= 0) name.substring(0, i) else name
|
||||||
val i = name.lastIndexOf('.')
|
Artifact(
|
||||||
val base = if (i >= 0) name.substring(0, i) else name
|
base,
|
||||||
Artifact(base, extract(name, DefaultType), extract(name, DefaultExtension), None, Vector.empty, Some(file.toURI.toURL))
|
extract(name, DefaultType),
|
||||||
}
|
extract(name, DefaultExtension),
|
||||||
def artifactName(scalaVersion: ScalaVersion, module: ModuleID, artifact: Artifact): String =
|
None,
|
||||||
{
|
Vector.empty,
|
||||||
import artifact._
|
Some(file.toURI.toURL)
|
||||||
val classifierStr = classifier match { case None => ""; case Some(c) => "-" + c }
|
)
|
||||||
val cross = CrossVersion(module.crossVersion, scalaVersion.full, scalaVersion.binary)
|
}
|
||||||
val base = CrossVersion.applyCross(artifact.name, cross)
|
def artifactName(scalaVersion: ScalaVersion, module: ModuleID, artifact: Artifact): String = {
|
||||||
base + "-" + module.revision + classifierStr + "." + artifact.extension
|
import artifact._
|
||||||
}
|
val classifierStr = classifier match { case None => ""; case Some(c) => "-" + c }
|
||||||
|
val cross = CrossVersion(module.crossVersion, scalaVersion.full, scalaVersion.binary)
|
||||||
|
val base = CrossVersion.applyCross(artifact.name, cross)
|
||||||
|
base + "-" + module.revision + classifierStr + "." + artifact.extension
|
||||||
|
}
|
||||||
|
|
||||||
val classifierTypeMap = Map(SourceClassifier -> SourceType, DocClassifier -> DocType)
|
val classifierTypeMap = Map(SourceClassifier -> SourceType, DocClassifier -> DocType)
|
||||||
@deprecated("Configuration should not be decided from the classifier.", "1.0")
|
@deprecated("Configuration should not be decided from the classifier.", "1.0")
|
||||||
|
|
@ -97,7 +121,8 @@ abstract class ArtifactFunctions {
|
||||||
Test
|
Test
|
||||||
else
|
else
|
||||||
Optional
|
Optional
|
||||||
def classifierType(classifier: String): String = classifierTypeMap.getOrElse(classifier.stripPrefix(TestsClassifier + "-"), DefaultType)
|
def classifierType(classifier: String): String =
|
||||||
|
classifierTypeMap.getOrElse(classifier.stripPrefix(TestsClassifier + "-"), DefaultType)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a classified explicit artifact, to be used when trying to resolve sources|javadocs from Maven. This is
|
* Create a classified explicit artifact, to be used when trying to resolve sources|javadocs from Maven. This is
|
||||||
|
|
@ -105,5 +130,12 @@ abstract class ArtifactFunctions {
|
||||||
* The artifact is created under the default configuration.
|
* The artifact is created under the default configuration.
|
||||||
*/
|
*/
|
||||||
def classified(name: String, classifier: String): Artifact =
|
def classified(name: String, classifier: String): Artifact =
|
||||||
Artifact(name, classifierType(classifier), DefaultExtension, Some(classifier), Vector.empty, None)
|
Artifact(
|
||||||
|
name,
|
||||||
|
classifierType(classifier),
|
||||||
|
DefaultExtension,
|
||||||
|
Some(classifier),
|
||||||
|
Vector.empty,
|
||||||
|
None
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
package sbt.librarymanagement
|
package sbt.librarymanagement
|
||||||
|
|
||||||
import org.apache.ivy.plugins.circular.{ CircularDependencyStrategy, WarnCircularDependencyStrategy, IgnoreCircularDependencyStrategy, ErrorCircularDependencyStrategy }
|
import org.apache.ivy.plugins.circular.{
|
||||||
|
CircularDependencyStrategy,
|
||||||
|
WarnCircularDependencyStrategy,
|
||||||
|
IgnoreCircularDependencyStrategy,
|
||||||
|
ErrorCircularDependencyStrategy
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around circular dependency strategy.
|
* Wrapper around circular dependency strategy.
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ package sbt.librarymanagement
|
||||||
object Configurations {
|
object Configurations {
|
||||||
def config(name: String) = Configuration(name)
|
def config(name: String) = Configuration(name)
|
||||||
def default: Seq[Configuration] = defaultMavenConfigurations
|
def default: Seq[Configuration] = defaultMavenConfigurations
|
||||||
def defaultMavenConfigurations: Seq[Configuration] = Seq(Compile, Runtime, Test, Provided, Optional)
|
def defaultMavenConfigurations: Seq[Configuration] =
|
||||||
|
Seq(Compile, Runtime, Test, Provided, Optional)
|
||||||
def defaultInternal: Seq[Configuration] = Seq(CompileInternal, RuntimeInternal, TestInternal)
|
def defaultInternal: Seq[Configuration] = Seq(CompileInternal, RuntimeInternal, TestInternal)
|
||||||
def auxiliary: Seq[Configuration] = Seq(Pom)
|
def auxiliary: Seq[Configuration] = Seq(Pom)
|
||||||
def names(cs: Seq[Configuration]) = cs.map(_.name)
|
def names(cs: Seq[Configuration]) = cs.map(_.name)
|
||||||
|
|
@ -24,7 +25,8 @@ object Configurations {
|
||||||
case _ => c
|
case _ => c
|
||||||
}
|
}
|
||||||
|
|
||||||
def internal(base: Configuration, ext: Configuration*) = config(base.name + "-internal").extend(ext: _*).hide
|
def internal(base: Configuration, ext: Configuration*) =
|
||||||
|
config(base.name + "-internal").extend(ext: _*).hide
|
||||||
def fullInternal(base: Configuration): Configuration = internal(base, base, Optional, Provided)
|
def fullInternal(base: Configuration): Configuration = internal(base, base, Optional, Provided)
|
||||||
def optionalInternal(base: Configuration): Configuration = internal(base, base, Optional)
|
def optionalInternal(base: Configuration): Configuration = internal(base, base, Optional)
|
||||||
|
|
||||||
|
|
@ -44,15 +46,24 @@ object Configurations {
|
||||||
|
|
||||||
private[sbt] val DefaultMavenConfiguration = defaultConfiguration(true)
|
private[sbt] val DefaultMavenConfiguration = defaultConfiguration(true)
|
||||||
private[sbt] val DefaultIvyConfiguration = defaultConfiguration(false)
|
private[sbt] val DefaultIvyConfiguration = defaultConfiguration(false)
|
||||||
private[sbt] def DefaultConfiguration(mavenStyle: Boolean) = if (mavenStyle) DefaultMavenConfiguration else DefaultIvyConfiguration
|
private[sbt] def DefaultConfiguration(mavenStyle: Boolean) =
|
||||||
private[sbt] def defaultConfiguration(mavenStyle: Boolean) = if (mavenStyle) Configurations.Compile else Configurations.Default
|
if (mavenStyle) DefaultMavenConfiguration else DefaultIvyConfiguration
|
||||||
private[sbt] def removeDuplicates(configs: Iterable[Configuration]) = Set(scala.collection.mutable.Map(configs.map(config => (config.name, config)).toSeq: _*).values.toList: _*)
|
private[sbt] def defaultConfiguration(mavenStyle: Boolean) =
|
||||||
|
if (mavenStyle) Configurations.Compile else Configurations.Default
|
||||||
|
private[sbt] def removeDuplicates(configs: Iterable[Configuration]) =
|
||||||
|
Set(
|
||||||
|
scala.collection.mutable
|
||||||
|
.Map(configs.map(config => (config.name, config)).toSeq: _*)
|
||||||
|
.values
|
||||||
|
.toList: _*
|
||||||
|
)
|
||||||
|
|
||||||
/** Returns true if the configuration should be under the influence of scalaVersion. */
|
/** Returns true if the configuration should be under the influence of scalaVersion. */
|
||||||
private[sbt] def underScalaVersion(c: Configuration): Boolean =
|
private[sbt] def underScalaVersion(c: Configuration): Boolean =
|
||||||
c match {
|
c match {
|
||||||
case Default | Compile | IntegrationTest | Provided | Runtime | Test | Optional |
|
case Default | Compile | IntegrationTest | Provided | Runtime | Test | Optional |
|
||||||
CompilerPlugin | CompileInternal | RuntimeInternal | TestInternal => true
|
CompilerPlugin | CompileInternal | RuntimeInternal | TestInternal =>
|
||||||
|
true
|
||||||
case config =>
|
case config =>
|
||||||
config.extendsConfigs exists underScalaVersion
|
config.extendsConfigs exists underScalaVersion
|
||||||
}
|
}
|
||||||
|
|
@ -68,8 +79,10 @@ abstract class ConfigurationExtra {
|
||||||
require(name != null && !name.isEmpty)
|
require(name != null && !name.isEmpty)
|
||||||
require(description != null)
|
require(description != null)
|
||||||
|
|
||||||
def describedAs(newDescription: String) = Configuration(name, newDescription, isPublic, extendsConfigs, transitive)
|
def describedAs(newDescription: String) =
|
||||||
def extend(configs: Configuration*) = Configuration(name, description, isPublic, configs.toVector ++ extendsConfigs, transitive)
|
Configuration(name, newDescription, isPublic, extendsConfigs, transitive)
|
||||||
|
def extend(configs: Configuration*) =
|
||||||
|
Configuration(name, description, isPublic, configs.toVector ++ extendsConfigs, transitive)
|
||||||
def notTransitive = intransitive
|
def notTransitive = intransitive
|
||||||
def intransitive = Configuration(name, description, isPublic, extendsConfigs, false)
|
def intransitive = Configuration(name, description, isPublic, extendsConfigs, false)
|
||||||
def hide = Configuration(name, description, false, extendsConfigs, transitive)
|
def hide = Configuration(name, description, false, extendsConfigs, transitive)
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,7 @@ import sbt.util.{ Logger, Level }
|
||||||
* A library foo_2.10 and foo_2.11 can potentially be both included on the
|
* A library foo_2.10 and foo_2.11 can potentially be both included on the
|
||||||
* library dependency graph by mistake, but it won't be caught by eviction.
|
* library dependency graph by mistake, but it won't be caught by eviction.
|
||||||
*/
|
*/
|
||||||
final case class ConflictWarning(label: String, level: Level.Value, failOnConflict: Boolean) {
|
final case class ConflictWarning(label: String, level: Level.Value, failOnConflict: Boolean) {}
|
||||||
}
|
|
||||||
object ConflictWarning {
|
object ConflictWarning {
|
||||||
def disable: ConflictWarning = ConflictWarning("", Level.Debug, false)
|
def disable: ConflictWarning = ConflictWarning("", Level.Debug, false)
|
||||||
|
|
||||||
|
|
@ -19,10 +18,15 @@ object ConflictWarning {
|
||||||
def apply(config: ConflictWarning, report: UpdateReport, log: Logger): Unit = {
|
def apply(config: ConflictWarning, report: UpdateReport, log: Logger): Unit = {
|
||||||
processCrossVersioned(config, report, log)
|
processCrossVersioned(config, report, log)
|
||||||
}
|
}
|
||||||
private[this] def processCrossVersioned(config: ConflictWarning, report: UpdateReport, log: Logger): Unit = {
|
private[this] def processCrossVersioned(
|
||||||
|
config: ConflictWarning,
|
||||||
|
report: UpdateReport,
|
||||||
|
log: Logger
|
||||||
|
): Unit = {
|
||||||
val crossMismatches = crossVersionMismatches(report)
|
val crossMismatches = crossVersionMismatches(report)
|
||||||
if (crossMismatches.nonEmpty) {
|
if (crossMismatches.nonEmpty) {
|
||||||
val pre = s"Modules were resolved with conflicting cross-version suffixes in ${config.label}:\n "
|
val pre =
|
||||||
|
s"Modules were resolved with conflicting cross-version suffixes in ${config.label}:\n "
|
||||||
val conflictMsgs =
|
val conflictMsgs =
|
||||||
for (((org, rawName), fullNames) <- crossMismatches) yield {
|
for (((org, rawName), fullNames) <- crossMismatches) yield {
|
||||||
val suffixes = fullNames.map(getCrossSuffix).mkString(", ")
|
val suffixes = fullNames.map(getCrossSuffix).mkString(", ")
|
||||||
|
|
@ -30,25 +34,26 @@ object ConflictWarning {
|
||||||
}
|
}
|
||||||
log.log(config.level, conflictMsgs.mkString(pre, "\n ", ""))
|
log.log(config.level, conflictMsgs.mkString(pre, "\n ", ""))
|
||||||
if (config.failOnConflict) {
|
if (config.failOnConflict) {
|
||||||
val summary = crossMismatches.map { case ((org, raw), _) => idString(org, raw) }.mkString(", ")
|
val summary =
|
||||||
|
crossMismatches.map { case ((org, raw), _) => idString(org, raw) }.mkString(", ")
|
||||||
sys.error("Conflicting cross-version suffixes in: " + summary)
|
sys.error("Conflicting cross-version suffixes in: " + summary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Map from (organization, rawName) to set of multiple full names. */
|
/** Map from (organization, rawName) to set of multiple full names. */
|
||||||
def crossVersionMismatches(report: UpdateReport): Map[(String, String), Set[String]] =
|
def crossVersionMismatches(report: UpdateReport): Map[(String, String), Set[String]] = {
|
||||||
{
|
val mismatches = report.configurations.flatMap { confReport =>
|
||||||
val mismatches = report.configurations.flatMap { confReport =>
|
groupByRawName(confReport.allModules).mapValues { modules =>
|
||||||
groupByRawName(confReport.allModules).mapValues { modules =>
|
val differentFullNames = modules.map(_.name).toSet
|
||||||
val differentFullNames = modules.map(_.name).toSet
|
if (differentFullNames.size > 1) differentFullNames else Set.empty[String]
|
||||||
if (differentFullNames.size > 1) differentFullNames else Set.empty[String]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
(Map.empty[(String, String), Set[String]] /: mismatches)(merge)
|
|
||||||
}
|
}
|
||||||
|
(Map.empty[(String, String), Set[String]] /: mismatches)(merge)
|
||||||
|
}
|
||||||
private[this] def merge[A, B](m: Map[A, Set[B]], b: (A, Set[B])): Map[A, Set[B]] =
|
private[this] def merge[A, B](m: Map[A, Set[B]], b: (A, Set[B])): Map[A, Set[B]] =
|
||||||
if (b._2.isEmpty) m else
|
if (b._2.isEmpty) m
|
||||||
|
else
|
||||||
m.updated(b._1, m.getOrElse(b._1, Set.empty) ++ b._2)
|
m.updated(b._1, m.getOrElse(b._1, Set.empty) ++ b._2)
|
||||||
|
|
||||||
private[this] def groupByRawName(ms: Seq[ModuleID]): Map[(String, String), Seq[ModuleID]] =
|
private[this] def groupByRawName(ms: Seq[ModuleID]): Map[(String, String), Seq[ModuleID]] =
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ object Credentials {
|
||||||
/** 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 {
|
||||||
|
|
@ -29,20 +30,26 @@ object Credentials {
|
||||||
def allDirect(sc: Seq[Credentials]): Seq[DirectCredentials] = sc map toDirect
|
def allDirect(sc: Seq[Credentials]): Seq[DirectCredentials] = sc map toDirect
|
||||||
def toDirect(c: Credentials): DirectCredentials = c match {
|
def toDirect(c: Credentials): DirectCredentials = c match {
|
||||||
case dc: DirectCredentials => dc
|
case dc: DirectCredentials => dc
|
||||||
case fc: FileCredentials => loadCredentials(fc.path) match {
|
case fc: FileCredentials =>
|
||||||
case Left(err) => sys.error(err)
|
loadCredentials(fc.path) match {
|
||||||
case Right(dc) => dc
|
case Left(err) => sys.error(err)
|
||||||
}
|
case Right(dc) => dc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def loadCredentials(path: File): Either[String, DirectCredentials] =
|
def loadCredentials(path: File): Either[String, DirectCredentials] =
|
||||||
if (path.exists) {
|
if (path.exists) {
|
||||||
val properties = read(path)
|
val properties = read(path)
|
||||||
def get(keys: List[String]) = keys.flatMap(properties.get).headOption.toRight(keys.head + " not specified in credentials file: " + path)
|
def get(keys: List[String]) =
|
||||||
|
keys
|
||||||
|
.flatMap(properties.get)
|
||||||
|
.headOption
|
||||||
|
.toRight(keys.head + " not specified in credentials file: " + path)
|
||||||
|
|
||||||
IvyUtil.separate(List(RealmKeys, HostKeys, UserKeys, PasswordKeys).map(get)) match {
|
IvyUtil.separate(List(RealmKeys, HostKeys, UserKeys, PasswordKeys).map(get)) match {
|
||||||
case (Nil, List(realm, host, user, pass)) => Right(new DirectCredentials(realm, host, user, pass))
|
case (Nil, List(realm, host, user, pass)) =>
|
||||||
case (errors, _) => Left(errors.mkString("\n"))
|
Right(new DirectCredentials(realm, host, user, pass))
|
||||||
|
case (errors, _) => Left(errors.mkString("\n"))
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
Left("Credentials file " + path + " does not exist")
|
Left("Credentials file " + path + " does not exist")
|
||||||
|
|
@ -59,16 +66,20 @@ object Credentials {
|
||||||
private[this] val PasswordKeys = List("password", "pwd", "pass", "passwd")
|
private[this] val PasswordKeys = List("password", "pwd", "pass", "passwd")
|
||||||
|
|
||||||
import collection.JavaConverters._
|
import collection.JavaConverters._
|
||||||
private[this] def read(from: File): Map[String, String] =
|
private[this] def read(from: File): Map[String, String] = {
|
||||||
{
|
val properties = new java.util.Properties
|
||||||
val properties = new java.util.Properties
|
IO.load(properties, from)
|
||||||
IO.load(properties, from)
|
properties.asScala.map { case (k, v) => (k.toString, v.toString.trim) }.toMap
|
||||||
properties.asScala.map { case (k, v) => (k.toString, v.toString.trim) }.toMap
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed trait Credentials
|
sealed trait Credentials
|
||||||
final class FileCredentials(val path: File) extends Credentials {
|
final class FileCredentials(val path: File) extends Credentials {
|
||||||
override def toString = "FileCredentials('" + path + "')"
|
override def toString = "FileCredentials('" + path + "')"
|
||||||
}
|
}
|
||||||
final class DirectCredentials(val realm: String, val host: String, val userName: String, val passwd: String) extends Credentials
|
final class DirectCredentials(
|
||||||
|
val realm: String,
|
||||||
|
val host: String,
|
||||||
|
val userName: String,
|
||||||
|
val passwd: String
|
||||||
|
) extends Credentials
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import sbt.internal.librarymanagement.cross.CrossVersionUtil
|
||||||
final case class ScalaVersion(full: String, binary: String)
|
final case class ScalaVersion(full: String, binary: String)
|
||||||
|
|
||||||
abstract class CrossVersionFunctions {
|
abstract class CrossVersionFunctions {
|
||||||
|
|
||||||
/** The first `major.minor` Scala version that the Scala binary version should be used for cross-versioning instead of the full version. */
|
/** The first `major.minor` Scala version that the Scala binary version should be used for cross-versioning instead of the full version. */
|
||||||
val TransitionScalaVersion = CrossVersionUtil.TransitionScalaVersion
|
val TransitionScalaVersion = CrossVersionUtil.TransitionScalaVersion
|
||||||
|
|
||||||
|
|
@ -50,7 +51,11 @@ abstract class CrossVersionFunctions {
|
||||||
* full version `fullVersion` and binary version `binaryVersion`. The behavior of the
|
* full version `fullVersion` and binary version `binaryVersion`. The behavior of the
|
||||||
* constructed function is as documented for the [[sbt.librarymanagement.CrossVersion]] datatypes.
|
* constructed function is as documented for the [[sbt.librarymanagement.CrossVersion]] datatypes.
|
||||||
*/
|
*/
|
||||||
def apply(cross: CrossVersion, fullVersion: String, binaryVersion: String): Option[String => String] =
|
def apply(
|
||||||
|
cross: CrossVersion,
|
||||||
|
fullVersion: String,
|
||||||
|
binaryVersion: String
|
||||||
|
): Option[String => String] =
|
||||||
cross match {
|
cross match {
|
||||||
case _: Disabled => None
|
case _: Disabled => None
|
||||||
case b: Binary => append(b.prefix + binaryVersion + b.suffix)
|
case b: Binary => append(b.prefix + binaryVersion + b.suffix)
|
||||||
|
|
@ -64,10 +69,15 @@ abstract class CrossVersionFunctions {
|
||||||
|
|
||||||
/** Constructs the cross-version function defined by `module` and `is`, if one is configured. */
|
/** Constructs the cross-version function defined by `module` and `is`, if one is configured. */
|
||||||
def apply(module: ModuleID, is: Option[IvyScala]): Option[String => String] =
|
def apply(module: ModuleID, is: Option[IvyScala]): Option[String => String] =
|
||||||
is flatMap { i => apply(module, i) }
|
is flatMap { i =>
|
||||||
|
apply(module, i)
|
||||||
|
}
|
||||||
|
|
||||||
/** Cross-version each `Artifact` in `artifacts` according to cross-version function `cross`. */
|
/** Cross-version each `Artifact` in `artifacts` according to cross-version function `cross`. */
|
||||||
def substituteCross(artifacts: Vector[Artifact], cross: Option[String => String]): Vector[Artifact] =
|
def substituteCross(
|
||||||
|
artifacts: Vector[Artifact],
|
||||||
|
cross: Option[String => String]
|
||||||
|
): Vector[Artifact] =
|
||||||
cross match {
|
cross match {
|
||||||
case None => artifacts
|
case None => artifacts
|
||||||
case Some(is) => substituteCrossA(artifacts, cross)
|
case Some(is) => substituteCrossA(artifacts, cross)
|
||||||
|
|
@ -83,9 +93,14 @@ abstract class CrossVersionFunctions {
|
||||||
name + "_" + cross
|
name + "_" + cross
|
||||||
|
|
||||||
/** Cross-versions `exclude` according to its `crossVersion`. */
|
/** Cross-versions `exclude` according to its `crossVersion`. */
|
||||||
private[sbt] def substituteCross(exclude: SbtExclusionRule, is: Option[IvyScala]): SbtExclusionRule = {
|
private[sbt] def substituteCross(
|
||||||
|
exclude: SbtExclusionRule,
|
||||||
|
is: Option[IvyScala]
|
||||||
|
): SbtExclusionRule = {
|
||||||
val fopt: Option[String => String] =
|
val fopt: Option[String => String] =
|
||||||
is flatMap { i => CrossVersion(exclude.crossVersion, i.scalaFullVersion, i.scalaBinaryVersion) }
|
is flatMap { i =>
|
||||||
|
CrossVersion(exclude.crossVersion, i.scalaFullVersion, i.scalaBinaryVersion)
|
||||||
|
}
|
||||||
exclude.withName(applyCross(exclude.name, fopt))
|
exclude.withName(applyCross(exclude.name, fopt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,7 +108,10 @@ abstract class CrossVersionFunctions {
|
||||||
def substituteCross(a: Artifact, cross: Option[String => String]): Artifact =
|
def substituteCross(a: Artifact, cross: Option[String => String]): Artifact =
|
||||||
a.withName(applyCross(a.name, cross))
|
a.withName(applyCross(a.name, cross))
|
||||||
|
|
||||||
private[sbt] def substituteCrossA(as: Vector[Artifact], cross: Option[String => String]): Vector[Artifact] =
|
private[sbt] def substituteCrossA(
|
||||||
|
as: Vector[Artifact],
|
||||||
|
cross: Option[String => String]
|
||||||
|
): Vector[Artifact] =
|
||||||
as.map(art => substituteCross(art, cross))
|
as.map(art => substituteCross(art, cross))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -101,14 +119,14 @@ abstract class CrossVersionFunctions {
|
||||||
* for the given full and binary Scala versions `scalaFullVersion` and `scalaBinaryVersion`
|
* for the given full and binary Scala versions `scalaFullVersion` and `scalaBinaryVersion`
|
||||||
* according to the ModuleID's cross-versioning setting.
|
* according to the ModuleID's cross-versioning setting.
|
||||||
*/
|
*/
|
||||||
def apply(scalaFullVersion: String, scalaBinaryVersion: String): ModuleID => ModuleID = m =>
|
def apply(scalaFullVersion: String, scalaBinaryVersion: String): ModuleID => ModuleID = m => {
|
||||||
{
|
val cross = apply(m.crossVersion, scalaFullVersion, scalaBinaryVersion)
|
||||||
val cross = apply(m.crossVersion, scalaFullVersion, scalaBinaryVersion)
|
if (cross.isDefined)
|
||||||
if (cross.isDefined)
|
m.withName(applyCross(m.name, cross))
|
||||||
m.withName(applyCross(m.name, cross)).withExplicitArtifacts(substituteCrossA(m.explicitArtifacts, cross))
|
.withExplicitArtifacts(substituteCrossA(m.explicitArtifacts, cross))
|
||||||
else
|
else
|
||||||
m
|
m
|
||||||
}
|
}
|
||||||
|
|
||||||
@deprecated("Use CrossVersion.isScalaApiCompatible or CrossVersion.isSbtApiCompatible", "0.13.0")
|
@deprecated("Use CrossVersion.isScalaApiCompatible or CrossVersion.isSbtApiCompatible", "0.13.0")
|
||||||
def isStable(v: String): Boolean = isScalaApiCompatible(v)
|
def isStable(v: String): Boolean = isScalaApiCompatible(v)
|
||||||
|
|
@ -152,6 +170,7 @@ abstract class CrossVersionFunctions {
|
||||||
def binarySbtVersion(full: String): String = CrossVersionUtil.binarySbtVersion(full)
|
def binarySbtVersion(full: String): String = CrossVersionUtil.binarySbtVersion(full)
|
||||||
|
|
||||||
@deprecated("Use CrossVersion.scalaApiVersion or CrossVersion.sbtApiVersion", "0.13.0")
|
@deprecated("Use CrossVersion.scalaApiVersion or CrossVersion.sbtApiVersion", "0.13.0")
|
||||||
def binaryVersion(full: String, cutoff: String): String = CrossVersionUtil.binaryVersion(full, cutoff)
|
def binaryVersion(full: String, cutoff: String): String =
|
||||||
|
CrossVersionUtil.binaryVersion(full, cutoff)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ import sbt.internal.librarymanagement._
|
||||||
import sbt.util.Logger
|
import sbt.util.Logger
|
||||||
import sbt.io.Hash
|
import sbt.io.Hash
|
||||||
|
|
||||||
class DefaultLibraryManagement(ivyConfiguration: IvyConfiguration, log: Logger) extends LibraryManagement {
|
class DefaultLibraryManagement(ivyConfiguration: IvyConfiguration, log: Logger)
|
||||||
|
extends LibraryManagement {
|
||||||
private[sbt] val ivySbt: IvySbt = new IvySbt(ivyConfiguration)
|
private[sbt] val ivySbt: IvySbt = new IvySbt(ivyConfiguration)
|
||||||
private val sbtOrgTemp = JsonUtil.sbtOrgTemp
|
private val sbtOrgTemp = JsonUtil.sbtOrgTemp
|
||||||
private val modulePrefixTemp = "temp-module-"
|
private val modulePrefixTemp = "temp-module-"
|
||||||
|
|
@ -22,12 +23,17 @@ class DefaultLibraryManagement(ivyConfiguration: IvyConfiguration, log: Logger)
|
||||||
|
|
||||||
def getModule(moduleId: ModuleID, ivyScala: Option[IvyScala]): ivySbt.Module = {
|
def getModule(moduleId: ModuleID, ivyScala: Option[IvyScala]): ivySbt.Module = {
|
||||||
val sha1 = Hash.toHex(Hash(moduleId.name))
|
val sha1 = Hash.toHex(Hash(moduleId.name))
|
||||||
val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, moduleId.revision).withConfigurations(moduleId.configurations)
|
val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, moduleId.revision)
|
||||||
|
.withConfigurations(moduleId.configurations)
|
||||||
getModule(dummyID, Vector(moduleId), UpdateOptions(), ivyScala)
|
getModule(dummyID, Vector(moduleId), UpdateOptions(), ivyScala)
|
||||||
}
|
}
|
||||||
|
|
||||||
def getModule(moduleId: ModuleID, deps: Vector[ModuleID],
|
def getModule(
|
||||||
uo: UpdateOptions = UpdateOptions(), ivyScala: Option[IvyScala]): ivySbt.Module = {
|
moduleId: ModuleID,
|
||||||
|
deps: Vector[ModuleID],
|
||||||
|
uo: UpdateOptions = UpdateOptions(),
|
||||||
|
ivyScala: Option[IvyScala]
|
||||||
|
): ivySbt.Module = {
|
||||||
val moduleSetting = InlineConfiguration(
|
val moduleSetting = InlineConfiguration(
|
||||||
validate = false,
|
validate = false,
|
||||||
ivyScala = ivyScala,
|
ivyScala = ivyScala,
|
||||||
|
|
@ -51,14 +57,29 @@ class DefaultLibraryManagement(ivyConfiguration: IvyConfiguration, log: Logger)
|
||||||
s"unknown"
|
s"unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
def update(module: ivySbt.Module, retrieveDirectory: File)(predicate: File => Boolean): Option[Seq[File]] = {
|
def update(module: ivySbt.Module, retrieveDirectory: File)(
|
||||||
|
predicate: File => Boolean
|
||||||
|
): Option[Seq[File]] = {
|
||||||
val specialArtifactTypes = Artifact.DefaultSourceTypes union Artifact.DefaultDocTypes
|
val specialArtifactTypes = Artifact.DefaultSourceTypes union Artifact.DefaultDocTypes
|
||||||
val artifactFilter = ArtifactTypeFilter.forbid(specialArtifactTypes)
|
val artifactFilter = ArtifactTypeFilter.forbid(specialArtifactTypes)
|
||||||
val retrieveConfiguration = RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern).withSync(false)
|
val retrieveConfiguration =
|
||||||
val updateConfiguration = UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly, artifactFilter)
|
RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern).withSync(false)
|
||||||
|
val updateConfiguration = UpdateConfiguration(
|
||||||
|
Some(retrieveConfiguration),
|
||||||
|
true,
|
||||||
|
UpdateLogging.DownloadOnly,
|
||||||
|
artifactFilter
|
||||||
|
)
|
||||||
|
|
||||||
log.debug(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.")
|
log.debug(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.")
|
||||||
IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, log) match {
|
IvyActions.updateEither(
|
||||||
|
module,
|
||||||
|
updateConfiguration,
|
||||||
|
UnresolvedWarningConfiguration(),
|
||||||
|
LogicalClock.unknown,
|
||||||
|
None,
|
||||||
|
log
|
||||||
|
) match {
|
||||||
case Left(unresolvedWarning) =>
|
case Left(unresolvedWarning) =>
|
||||||
log.debug(s"Couldn't retrieve module ${dependenciesNames(module)}.")
|
log.debug(s"Couldn't retrieve module ${dependenciesNames(module)}.")
|
||||||
None
|
None
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,25 @@ package sbt.librarymanagement
|
||||||
import sbt.io.{ AllPassFilter, NameFilter }
|
import sbt.io.{ AllPassFilter, NameFilter }
|
||||||
|
|
||||||
trait DependencyFilterExtra {
|
trait DependencyFilterExtra {
|
||||||
def moduleFilter(organization: NameFilter = AllPassFilter, name: NameFilter = AllPassFilter, revision: NameFilter = AllPassFilter): ModuleFilter =
|
def moduleFilter(
|
||||||
|
organization: NameFilter = AllPassFilter,
|
||||||
|
name: NameFilter = AllPassFilter,
|
||||||
|
revision: NameFilter = AllPassFilter
|
||||||
|
): ModuleFilter =
|
||||||
new ModuleFilter {
|
new ModuleFilter {
|
||||||
def apply(m: ModuleID): Boolean = organization.accept(m.organization) && name.accept(m.name) && revision.accept(m.revision)
|
def apply(m: ModuleID): Boolean =
|
||||||
|
organization.accept(m.organization) && name.accept(m.name) && revision.accept(m.revision)
|
||||||
}
|
}
|
||||||
def artifactFilter(name: NameFilter = AllPassFilter, `type`: NameFilter = AllPassFilter, extension: NameFilter = AllPassFilter, classifier: NameFilter = AllPassFilter): ArtifactFilter =
|
def artifactFilter(
|
||||||
|
name: NameFilter = AllPassFilter,
|
||||||
|
`type`: NameFilter = AllPassFilter,
|
||||||
|
extension: NameFilter = AllPassFilter,
|
||||||
|
classifier: NameFilter = AllPassFilter
|
||||||
|
): ArtifactFilter =
|
||||||
new ArtifactFilter {
|
new ArtifactFilter {
|
||||||
def apply(a: Artifact): Boolean = name.accept(a.name) && `type`.accept(a.`type`) && extension.accept(a.extension) && classifier.accept(a.classifier getOrElse "")
|
def apply(a: Artifact): Boolean =
|
||||||
|
name.accept(a.name) && `type`.accept(a.`type`) && extension.accept(a.extension) && classifier
|
||||||
|
.accept(a.classifier getOrElse "")
|
||||||
}
|
}
|
||||||
def configurationFilter(name: NameFilter = AllPassFilter): ConfigurationFilter =
|
def configurationFilter(name: NameFilter = AllPassFilter): ConfigurationFilter =
|
||||||
new ConfigurationFilter {
|
new ConfigurationFilter {
|
||||||
|
|
@ -20,18 +32,32 @@ trait DependencyFilterExtra {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
object DependencyFilter extends DependencyFilterExtra {
|
object DependencyFilter extends DependencyFilterExtra {
|
||||||
def make(configuration: ConfigurationFilter = configurationFilter(), module: ModuleFilter = moduleFilter(), artifact: ArtifactFilter = artifactFilter()): DependencyFilter =
|
def make(
|
||||||
|
configuration: ConfigurationFilter = configurationFilter(),
|
||||||
|
module: ModuleFilter = moduleFilter(),
|
||||||
|
artifact: ArtifactFilter = artifactFilter()
|
||||||
|
): DependencyFilter =
|
||||||
new DependencyFilter {
|
new DependencyFilter {
|
||||||
def apply(c: String, m: ModuleID, a: Artifact): Boolean = configuration(c) && module(m) && artifact(a)
|
def apply(c: String, m: ModuleID, a: Artifact): Boolean =
|
||||||
|
configuration(c) && module(m) && artifact(a)
|
||||||
}
|
}
|
||||||
def apply(x: DependencyFilter, y: DependencyFilter, combine: (Boolean, Boolean) => Boolean): DependencyFilter =
|
def apply(
|
||||||
|
x: DependencyFilter,
|
||||||
|
y: DependencyFilter,
|
||||||
|
combine: (Boolean, Boolean) => Boolean
|
||||||
|
): DependencyFilter =
|
||||||
new DependencyFilter {
|
new DependencyFilter {
|
||||||
def apply(c: String, m: ModuleID, a: Artifact): Boolean = combine(x(c, m, a), y(c, m, a))
|
def apply(c: String, m: ModuleID, a: Artifact): Boolean = combine(x(c, m, a), y(c, m, a))
|
||||||
}
|
}
|
||||||
def allPass: DependencyFilter = configurationFilter()
|
def allPass: DependencyFilter = configurationFilter()
|
||||||
implicit def fnToModuleFilter(f: ModuleID => Boolean): ModuleFilter = new ModuleFilter { def apply(m: ModuleID) = f(m) }
|
implicit def fnToModuleFilter(f: ModuleID => Boolean): ModuleFilter = new ModuleFilter {
|
||||||
implicit def fnToArtifactFilter(f: Artifact => Boolean): ArtifactFilter = new ArtifactFilter { def apply(m: Artifact) = f(m) }
|
def apply(m: ModuleID) = f(m)
|
||||||
implicit def fnToConfigurationFilter(f: String => Boolean): ConfigurationFilter = new ConfigurationFilter { def apply(c: String) = f(c) }
|
}
|
||||||
|
implicit def fnToArtifactFilter(f: Artifact => Boolean): ArtifactFilter = new ArtifactFilter {
|
||||||
|
def apply(m: Artifact) = f(m)
|
||||||
|
}
|
||||||
|
implicit def fnToConfigurationFilter(f: String => Boolean): ConfigurationFilter =
|
||||||
|
new ConfigurationFilter { def apply(c: String) = f(c) }
|
||||||
implicit def subDepFilterToFn[Arg](f: SubDepFilter[Arg, _]): Arg => Boolean = f apply _
|
implicit def subDepFilterToFn[Arg](f: SubDepFilter[Arg, _]): Arg => Boolean = f apply _
|
||||||
}
|
}
|
||||||
trait DependencyFilter {
|
trait DependencyFilter {
|
||||||
|
|
@ -40,23 +66,34 @@ trait DependencyFilter {
|
||||||
final def ||(o: DependencyFilter) = DependencyFilter(this, o, _ || _)
|
final def ||(o: DependencyFilter) = DependencyFilter(this, o, _ || _)
|
||||||
final def --(o: DependencyFilter) = DependencyFilter(this, o, _ && !_)
|
final def --(o: DependencyFilter) = DependencyFilter(this, o, _ && !_)
|
||||||
}
|
}
|
||||||
sealed trait SubDepFilter[Arg, Self <: SubDepFilter[Arg, Self]] extends DependencyFilter { self: Self =>
|
sealed trait SubDepFilter[Arg, Self <: SubDepFilter[Arg, Self]] extends DependencyFilter {
|
||||||
|
self: Self =>
|
||||||
def apply(a: Arg): Boolean
|
def apply(a: Arg): Boolean
|
||||||
protected def make(f: Arg => Boolean): Self
|
protected def make(f: Arg => Boolean): Self
|
||||||
final def &(o: Self): Self = combine(o, _ && _)
|
final def &(o: Self): Self = combine(o, _ && _)
|
||||||
final def |(o: Self): Self = combine(o, _ || _)
|
final def |(o: Self): Self = combine(o, _ || _)
|
||||||
final def -(o: Self): Self = combine(o, _ && !_)
|
final def -(o: Self): Self = combine(o, _ && !_)
|
||||||
private[this] def combine(o: Self, f: (Boolean, Boolean) => Boolean): Self = make((m: Arg) => f(this(m), o(m)))
|
private[this] def combine(o: Self, f: (Boolean, Boolean) => Boolean): Self =
|
||||||
|
make((m: Arg) => f(this(m), o(m)))
|
||||||
}
|
}
|
||||||
trait ModuleFilter extends SubDepFilter[ModuleID, ModuleFilter] {
|
trait ModuleFilter extends SubDepFilter[ModuleID, ModuleFilter] {
|
||||||
protected final def make(f: ModuleID => Boolean) = new ModuleFilter { def apply(m: ModuleID) = f(m) }
|
protected final def make(f: ModuleID => Boolean) = new ModuleFilter {
|
||||||
final def apply(configuration: String, module: ModuleID, artifact: Artifact): Boolean = apply(module)
|
def apply(m: ModuleID) = f(m)
|
||||||
|
}
|
||||||
|
final def apply(configuration: String, module: ModuleID, artifact: Artifact): Boolean =
|
||||||
|
apply(module)
|
||||||
}
|
}
|
||||||
trait ArtifactFilter extends SubDepFilter[Artifact, ArtifactFilter] {
|
trait ArtifactFilter extends SubDepFilter[Artifact, ArtifactFilter] {
|
||||||
protected final def make(f: Artifact => Boolean) = new ArtifactFilter { def apply(m: Artifact) = f(m) }
|
protected final def make(f: Artifact => Boolean) = new ArtifactFilter {
|
||||||
final def apply(configuration: String, module: ModuleID, artifact: Artifact): Boolean = apply(artifact)
|
def apply(m: Artifact) = f(m)
|
||||||
|
}
|
||||||
|
final def apply(configuration: String, module: ModuleID, artifact: Artifact): Boolean =
|
||||||
|
apply(artifact)
|
||||||
}
|
}
|
||||||
trait ConfigurationFilter extends SubDepFilter[String, ConfigurationFilter] {
|
trait ConfigurationFilter extends SubDepFilter[String, ConfigurationFilter] {
|
||||||
protected final def make(f: String => Boolean) = new ConfigurationFilter { def apply(m: String) = f(m) }
|
protected final def make(f: String => Boolean) = new ConfigurationFilter {
|
||||||
final def apply(configuration: String, module: ModuleID, artifact: Artifact): Boolean = apply(configuration)
|
def apply(m: String) = f(m)
|
||||||
|
}
|
||||||
|
final def apply(configuration: String, module: ModuleID, artifact: Artifact): Boolean =
|
||||||
|
apply(configuration)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@ import sbt.util.ShowLines
|
||||||
import sbt.internal.librarymanagement.{ InlineConfiguration, IvySbt }
|
import sbt.internal.librarymanagement.{ InlineConfiguration, IvySbt }
|
||||||
|
|
||||||
final class EvictionWarningOptions private[sbt] (
|
final class EvictionWarningOptions private[sbt] (
|
||||||
val configurations: Seq[Configuration],
|
val configurations: Seq[Configuration],
|
||||||
val warnScalaVersionEviction: Boolean,
|
val warnScalaVersionEviction: Boolean,
|
||||||
val warnDirectEvictions: Boolean,
|
val warnDirectEvictions: Boolean,
|
||||||
val warnTransitiveEvictions: Boolean,
|
val warnTransitiveEvictions: Boolean,
|
||||||
val infoAllEvictions: Boolean,
|
val infoAllEvictions: Boolean,
|
||||||
val showCallers: Boolean,
|
val showCallers: Boolean,
|
||||||
val guessCompatible: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean]
|
val guessCompatible: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean]
|
||||||
) {
|
) {
|
||||||
private[sbt] def configStrings = configurations map { _.name }
|
private[sbt] def configStrings = configurations map { _.name }
|
||||||
|
|
||||||
|
|
@ -30,17 +30,20 @@ final class EvictionWarningOptions private[sbt] (
|
||||||
copy(infoAllEvictions = infoAllEvictions)
|
copy(infoAllEvictions = infoAllEvictions)
|
||||||
def withShowCallers(showCallers: Boolean): EvictionWarningOptions =
|
def withShowCallers(showCallers: Boolean): EvictionWarningOptions =
|
||||||
copy(showCallers = showCallers)
|
copy(showCallers = showCallers)
|
||||||
def withGuessCompatible(guessCompatible: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean]): EvictionWarningOptions =
|
def withGuessCompatible(
|
||||||
|
guessCompatible: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean]
|
||||||
|
): EvictionWarningOptions =
|
||||||
copy(guessCompatible = guessCompatible)
|
copy(guessCompatible = guessCompatible)
|
||||||
|
|
||||||
private[sbt] def copy(
|
private[sbt] def copy(
|
||||||
configurations: Seq[Configuration] = configurations,
|
configurations: Seq[Configuration] = configurations,
|
||||||
warnScalaVersionEviction: Boolean = warnScalaVersionEviction,
|
warnScalaVersionEviction: Boolean = warnScalaVersionEviction,
|
||||||
warnDirectEvictions: Boolean = warnDirectEvictions,
|
warnDirectEvictions: Boolean = warnDirectEvictions,
|
||||||
warnTransitiveEvictions: Boolean = warnTransitiveEvictions,
|
warnTransitiveEvictions: Boolean = warnTransitiveEvictions,
|
||||||
infoAllEvictions: Boolean = infoAllEvictions,
|
infoAllEvictions: Boolean = infoAllEvictions,
|
||||||
showCallers: Boolean = showCallers,
|
showCallers: Boolean = showCallers,
|
||||||
guessCompatible: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean] = guessCompatible
|
guessCompatible: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean] =
|
||||||
|
guessCompatible
|
||||||
): EvictionWarningOptions =
|
): EvictionWarningOptions =
|
||||||
new EvictionWarningOptions(
|
new EvictionWarningOptions(
|
||||||
configurations = configurations,
|
configurations = configurations,
|
||||||
|
|
@ -63,19 +66,26 @@ object EvictionWarningOptions {
|
||||||
|
|
||||||
lazy val defaultGuess: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean] =
|
lazy val defaultGuess: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean] =
|
||||||
guessSecondSegment orElse guessSemVer orElse guessFalse
|
guessSecondSegment orElse guessSemVer orElse guessFalse
|
||||||
lazy val guessSecondSegment: PartialFunction[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean] = {
|
lazy val guessSecondSegment
|
||||||
case (m1, Some(m2), Some(ivyScala)) if m2.name.endsWith("_" + ivyScala.scalaFullVersion) || m2.name.endsWith("_" + ivyScala.scalaBinaryVersion) =>
|
: PartialFunction[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean] = {
|
||||||
|
case (m1, Some(m2), Some(ivyScala))
|
||||||
|
if m2.name.endsWith("_" + ivyScala.scalaFullVersion) || m2.name.endsWith(
|
||||||
|
"_" + ivyScala.scalaBinaryVersion
|
||||||
|
) =>
|
||||||
(m1.revision, m2.revision) match {
|
(m1.revision, m2.revision) match {
|
||||||
case (VersionNumber(ns1, ts1, es1), VersionNumber(ns2, ts2, es2)) =>
|
case (VersionNumber(ns1, ts1, es1), VersionNumber(ns2, ts2, es2)) =>
|
||||||
VersionNumber.SecondSegment.isCompatible(VersionNumber(ns1, ts1, es1), VersionNumber(ns2, ts2, es2))
|
VersionNumber.SecondSegment
|
||||||
|
.isCompatible(VersionNumber(ns1, ts1, es1), VersionNumber(ns2, ts2, es2))
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lazy val guessSemVer: PartialFunction[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean] = {
|
lazy val guessSemVer
|
||||||
|
: PartialFunction[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean] = {
|
||||||
case (m1, Some(m2), _) =>
|
case (m1, Some(m2), _) =>
|
||||||
(m1.revision, m2.revision) match {
|
(m1.revision, m2.revision) match {
|
||||||
case (VersionNumber(ns1, ts1, es1), VersionNumber(ns2, ts2, es2)) =>
|
case (VersionNumber(ns1, ts1, es1), VersionNumber(ns2, ts2, es2)) =>
|
||||||
VersionNumber.SemVer.isCompatible(VersionNumber(ns1, ts1, es1), VersionNumber(ns2, ts2, es2))
|
VersionNumber.SemVer
|
||||||
|
.isCompatible(VersionNumber(ns1, ts1, es1), VersionNumber(ns2, ts2, es2))
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -85,12 +95,12 @@ object EvictionWarningOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
final class EvictionPair private[sbt] (
|
final class EvictionPair private[sbt] (
|
||||||
val organization: String,
|
val organization: String,
|
||||||
val name: String,
|
val name: String,
|
||||||
val winner: Option[ModuleReport],
|
val winner: Option[ModuleReport],
|
||||||
val evicteds: Vector[ModuleReport],
|
val evicteds: Vector[ModuleReport],
|
||||||
val includesDirect: Boolean,
|
val includesDirect: Boolean,
|
||||||
val showCallers: Boolean
|
val showCallers: Boolean
|
||||||
) {
|
) {
|
||||||
override def toString: String =
|
override def toString: String =
|
||||||
EvictionPair.evictionPairLines.showLines(this).mkString
|
EvictionPair.evictionPairLines.showLines(this).mkString
|
||||||
|
|
@ -118,8 +128,7 @@ object EvictionPair {
|
||||||
r.callers match {
|
r.callers match {
|
||||||
case Seq() => ""
|
case Seq() => ""
|
||||||
case cs => (cs map { _.caller.toString }).mkString(" (caller: ", ", ", ")")
|
case cs => (cs map { _.caller.toString }).mkString(" (caller: ", ", ", ")")
|
||||||
}
|
} else ""
|
||||||
else ""
|
|
||||||
r.module.revision + callers
|
r.module.revision + callers
|
||||||
}) map { " -> " + _ } getOrElse ""
|
}) map { " -> " + _ } getOrElse ""
|
||||||
Seq(s"\t* ${a.organization}:${a.name}:${revsStr}$winnerRev")
|
Seq(s"\t* ${a.organization}:${a.name}:${revsStr}$winnerRev")
|
||||||
|
|
@ -127,29 +136,42 @@ object EvictionPair {
|
||||||
}
|
}
|
||||||
|
|
||||||
final class EvictionWarning private[sbt] (
|
final class EvictionWarning private[sbt] (
|
||||||
val options: EvictionWarningOptions,
|
val options: EvictionWarningOptions,
|
||||||
val scalaEvictions: Seq[EvictionPair],
|
val scalaEvictions: Seq[EvictionPair],
|
||||||
val directEvictions: Seq[EvictionPair],
|
val directEvictions: Seq[EvictionPair],
|
||||||
val transitiveEvictions: Seq[EvictionPair],
|
val transitiveEvictions: Seq[EvictionPair],
|
||||||
val allEvictions: Seq[EvictionPair]
|
val allEvictions: Seq[EvictionPair]
|
||||||
) {
|
) {
|
||||||
def reportedEvictions: Seq[EvictionPair] = scalaEvictions ++ directEvictions ++ transitiveEvictions
|
def reportedEvictions: Seq[EvictionPair] =
|
||||||
|
scalaEvictions ++ directEvictions ++ transitiveEvictions
|
||||||
private[sbt] def infoAllTheThings: List[String] = EvictionWarning.infoAllTheThings(this)
|
private[sbt] def infoAllTheThings: List[String] = EvictionWarning.infoAllTheThings(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
object EvictionWarning {
|
object EvictionWarning {
|
||||||
def apply(module: IvySbt#Module, options: EvictionWarningOptions, report: UpdateReport, log: Logger): EvictionWarning = {
|
def apply(
|
||||||
|
module: IvySbt#Module,
|
||||||
|
options: EvictionWarningOptions,
|
||||||
|
report: UpdateReport,
|
||||||
|
log: Logger
|
||||||
|
): EvictionWarning = {
|
||||||
val evictions = buildEvictions(options, report)
|
val evictions = buildEvictions(options, report)
|
||||||
processEvictions(module, options, evictions)
|
processEvictions(module, options, evictions)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def buildEvictions(options: EvictionWarningOptions, report: UpdateReport): Seq[OrganizationArtifactReport] = {
|
private[sbt] def buildEvictions(
|
||||||
|
options: EvictionWarningOptions,
|
||||||
|
report: UpdateReport
|
||||||
|
): Seq[OrganizationArtifactReport] = {
|
||||||
val buffer: mutable.ListBuffer[OrganizationArtifactReport] = mutable.ListBuffer()
|
val buffer: mutable.ListBuffer[OrganizationArtifactReport] = mutable.ListBuffer()
|
||||||
val confs = report.configurations filter { x => options.configStrings contains x.configuration }
|
val confs = report.configurations filter { x =>
|
||||||
|
options.configStrings contains x.configuration
|
||||||
|
}
|
||||||
confs flatMap { confReport =>
|
confs flatMap { confReport =>
|
||||||
confReport.details map { detail =>
|
confReport.details map { detail =>
|
||||||
if ((detail.modules exists { _.evicted }) &&
|
if ((detail.modules exists { _.evicted }) &&
|
||||||
!(buffer exists { x => (x.organization == detail.organization) && (x.name == detail.name) })) {
|
!(buffer exists { x =>
|
||||||
|
(x.organization == detail.organization) && (x.name == detail.name)
|
||||||
|
})) {
|
||||||
buffer += detail
|
buffer += detail
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +179,11 @@ object EvictionWarning {
|
||||||
buffer.toList.toVector
|
buffer.toList.toVector
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def isScalaArtifact(module: IvySbt#Module, organization: String, name: String): Boolean =
|
private[sbt] def isScalaArtifact(
|
||||||
|
module: IvySbt#Module,
|
||||||
|
organization: String,
|
||||||
|
name: String
|
||||||
|
): Boolean =
|
||||||
module.moduleSettings.ivyScala match {
|
module.moduleSettings.ivyScala match {
|
||||||
case Some(s) =>
|
case Some(s) =>
|
||||||
organization == s.scalaOrganization &&
|
organization == s.scalaOrganization &&
|
||||||
|
|
@ -165,7 +191,11 @@ object EvictionWarning {
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def processEvictions(module: IvySbt#Module, options: EvictionWarningOptions, reports: Seq[OrganizationArtifactReport]): EvictionWarning = {
|
private[sbt] def processEvictions(
|
||||||
|
module: IvySbt#Module,
|
||||||
|
options: EvictionWarningOptions,
|
||||||
|
reports: Seq[OrganizationArtifactReport]
|
||||||
|
): EvictionWarning = {
|
||||||
val directDependencies = module.moduleSettings match {
|
val directDependencies = module.moduleSettings match {
|
||||||
case x: InlineConfiguration => x.dependencies
|
case x: InlineConfiguration => x.dependencies
|
||||||
case _ => Vector.empty
|
case _ => Vector.empty
|
||||||
|
|
@ -178,19 +208,29 @@ object EvictionWarning {
|
||||||
(directDependencies exists { dep =>
|
(directDependencies exists { dep =>
|
||||||
(detail.organization == dep.organization) && (detail.name == dep.name)
|
(detail.organization == dep.organization) && (detail.name == dep.name)
|
||||||
})
|
})
|
||||||
new EvictionPair(detail.organization, detail.name, winner, evicteds, includesDirect, options.showCallers)
|
new EvictionPair(
|
||||||
|
detail.organization,
|
||||||
|
detail.name,
|
||||||
|
winner,
|
||||||
|
evicteds,
|
||||||
|
includesDirect,
|
||||||
|
options.showCallers
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val scalaEvictions: mutable.ListBuffer[EvictionPair] = mutable.ListBuffer()
|
val scalaEvictions: mutable.ListBuffer[EvictionPair] = mutable.ListBuffer()
|
||||||
val directEvictions: mutable.ListBuffer[EvictionPair] = mutable.ListBuffer()
|
val directEvictions: mutable.ListBuffer[EvictionPair] = mutable.ListBuffer()
|
||||||
val transitiveEvictions: mutable.ListBuffer[EvictionPair] = mutable.ListBuffer()
|
val transitiveEvictions: mutable.ListBuffer[EvictionPair] = mutable.ListBuffer()
|
||||||
def guessCompatible(p: EvictionPair): Boolean =
|
def guessCompatible(p: EvictionPair): Boolean =
|
||||||
p.evicteds forall { r =>
|
p.evicteds forall { r =>
|
||||||
options.guessCompatible((r.module, p.winner map { _.module }, module.moduleSettings.ivyScala))
|
options.guessCompatible(
|
||||||
|
(r.module, p.winner map { _.module }, module.moduleSettings.ivyScala)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
pairs foreach {
|
pairs foreach {
|
||||||
case p if isScalaArtifact(module, p.organization, p.name) =>
|
case p if isScalaArtifact(module, p.organization, p.name) =>
|
||||||
(module.moduleSettings.ivyScala, p.winner) match {
|
(module.moduleSettings.ivyScala, p.winner) match {
|
||||||
case (Some(s), Some(winner)) if (s.scalaFullVersion != winner.module.revision) && options.warnScalaVersionEviction =>
|
case (Some(s), Some(winner))
|
||||||
|
if (s.scalaFullVersion != winner.module.revision) && options.warnScalaVersionEviction =>
|
||||||
scalaEvictions += p
|
scalaEvictions += p
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
|
|
@ -203,8 +243,13 @@ object EvictionWarning {
|
||||||
transitiveEvictions += p
|
transitiveEvictions += p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new EvictionWarning(options, scalaEvictions.toList,
|
new EvictionWarning(
|
||||||
directEvictions.toList, transitiveEvictions.toList, pairs)
|
options,
|
||||||
|
scalaEvictions.toList,
|
||||||
|
directEvictions.toList,
|
||||||
|
transitiveEvictions.toList,
|
||||||
|
pairs
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
implicit val evictionWarningLines: ShowLines[EvictionWarning] = ShowLines { a: EvictionWarning =>
|
implicit val evictionWarningLines: ShowLines[EvictionWarning] = ShowLines { a: EvictionWarning =>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,10 @@ abstract class ArtifactTypeFilterExtra {
|
||||||
def types: Set[String]
|
def types: Set[String]
|
||||||
def inverted: Boolean
|
def inverted: Boolean
|
||||||
|
|
||||||
protected[this] def copy(types: Set[String] = types, inverted: Boolean = inverted): ArtifactTypeFilter
|
protected[this] def copy(
|
||||||
|
types: Set[String] = types,
|
||||||
|
inverted: Boolean = inverted
|
||||||
|
): ArtifactTypeFilter
|
||||||
|
|
||||||
def invert = copy(inverted = !inverted)
|
def invert = copy(inverted = !inverted)
|
||||||
def apply(a: descriptor.Artifact): Boolean = (types contains a.getType) ^ inverted
|
def apply(a: descriptor.Artifact): Boolean = (types contains a.getType) ^ inverted
|
||||||
|
|
@ -25,7 +28,9 @@ abstract class ArtifactTypeFilterFunctions {
|
||||||
def forbid(types: Set[String]) = ArtifactTypeFilter(types, true)
|
def forbid(types: Set[String]) = ArtifactTypeFilter(types, true)
|
||||||
|
|
||||||
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 { case a: descriptor.Artifact => f.apply(a) }
|
override def accept(o: Object): Boolean = Option(o) exists {
|
||||||
|
case a: descriptor.Artifact => f.apply(a)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,17 @@ object ScalaArtifacts {
|
||||||
|
|
||||||
def libraryDependency(version: String): ModuleID = ModuleID(Organization, LibraryID, version)
|
def libraryDependency(version: String): ModuleID = ModuleID(Organization, LibraryID, version)
|
||||||
|
|
||||||
private[sbt] def toolDependencies(org: String, version: String, isDotty: Boolean = false): Seq[ModuleID] =
|
private[sbt] def toolDependencies(
|
||||||
|
org: String,
|
||||||
|
version: String,
|
||||||
|
isDotty: Boolean = false
|
||||||
|
): Seq[ModuleID] =
|
||||||
if (isDotty)
|
if (isDotty)
|
||||||
Seq(ModuleID(org, DottyIDPrefix, version).withConfigurations(Some(Configurations.ScalaTool.name + "->default(compile)"))
|
Seq(
|
||||||
.withCrossVersion(CrossVersion.binary))
|
ModuleID(org, DottyIDPrefix, version)
|
||||||
|
.withConfigurations(Some(Configurations.ScalaTool.name + "->default(compile)"))
|
||||||
|
.withCrossVersion(CrossVersion.binary)
|
||||||
|
)
|
||||||
else
|
else
|
||||||
Seq(
|
Seq(
|
||||||
scalaToolDependency(org, ScalaArtifacts.CompilerID, version),
|
scalaToolDependency(org, ScalaArtifacts.CompilerID, version),
|
||||||
|
|
@ -37,7 +44,9 @@ object ScalaArtifacts {
|
||||||
)
|
)
|
||||||
|
|
||||||
private[this] def scalaToolDependency(org: String, id: String, version: String): ModuleID =
|
private[this] def scalaToolDependency(org: String, id: String, version: String): ModuleID =
|
||||||
ModuleID(org, id, version).withConfigurations(Some(Configurations.ScalaTool.name + "->default,optional(default)"))
|
ModuleID(org, id, version).withConfigurations(
|
||||||
|
Some(Configurations.ScalaTool.name + "->default,optional(default)")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
object SbtArtifacts {
|
object SbtArtifacts {
|
||||||
val Organization = "org.scala-sbt"
|
val Organization = "org.scala-sbt"
|
||||||
|
|
@ -46,17 +55,39 @@ object SbtArtifacts {
|
||||||
import ScalaArtifacts._
|
import ScalaArtifacts._
|
||||||
|
|
||||||
private[sbt] abstract class IvyScalaFunctions {
|
private[sbt] abstract class IvyScalaFunctions {
|
||||||
|
|
||||||
/** Performs checks/adds filters on Scala dependencies (if enabled in IvyScala). */
|
/** Performs checks/adds filters on Scala dependencies (if enabled in IvyScala). */
|
||||||
def checkModule(module: DefaultModuleDescriptor, conf: String, scalaVersionConfigs: Vector[String], log: Logger)(check: IvyScala): Unit = {
|
def checkModule(
|
||||||
|
module: DefaultModuleDescriptor,
|
||||||
|
conf: String,
|
||||||
|
scalaVersionConfigs: Vector[String],
|
||||||
|
log: Logger
|
||||||
|
)(check: IvyScala): Unit = {
|
||||||
if (check.checkExplicit)
|
if (check.checkExplicit)
|
||||||
checkDependencies(module, check.scalaOrganization, check.scalaArtifacts, check.scalaBinaryVersion, scalaVersionConfigs, log)
|
checkDependencies(
|
||||||
|
module,
|
||||||
|
check.scalaOrganization,
|
||||||
|
check.scalaArtifacts,
|
||||||
|
check.scalaBinaryVersion,
|
||||||
|
scalaVersionConfigs,
|
||||||
|
log
|
||||||
|
)
|
||||||
if (check.filterImplicit)
|
if (check.filterImplicit)
|
||||||
excludeScalaJars(module, check.configurations)
|
excludeScalaJars(module, check.configurations)
|
||||||
if (check.overrideScalaVersion)
|
if (check.overrideScalaVersion)
|
||||||
overrideScalaVersion(module, check.scalaOrganization, check.scalaFullVersion, scalaVersionConfigs)
|
overrideScalaVersion(
|
||||||
|
module,
|
||||||
|
check.scalaOrganization,
|
||||||
|
check.scalaFullVersion,
|
||||||
|
scalaVersionConfigs
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverrideScalaMediator(scalaOrganization: String, scalaVersion: String, scalaVersionConfigs0: Vector[String]) extends DependencyDescriptorMediator {
|
class OverrideScalaMediator(
|
||||||
|
scalaOrganization: String,
|
||||||
|
scalaVersion: String,
|
||||||
|
scalaVersionConfigs0: Vector[String]
|
||||||
|
) extends DependencyDescriptorMediator {
|
||||||
private[this] val scalaVersionConfigs = scalaVersionConfigs0.toSet
|
private[this] val scalaVersionConfigs = scalaVersionConfigs0.toSet
|
||||||
def mediate(dd: DependencyDescriptor): DependencyDescriptor = {
|
def mediate(dd: DependencyDescriptor): DependencyDescriptor = {
|
||||||
// Mediate only for the dependencies in scalaVersion configurations. https://github.com/sbt/sbt/issues/2786
|
// Mediate only for the dependencies in scalaVersion configurations. https://github.com/sbt/sbt/issues/2786
|
||||||
|
|
@ -79,8 +110,15 @@ private[sbt] abstract class IvyScalaFunctions {
|
||||||
if (mrid == null) mrid
|
if (mrid == null) mrid
|
||||||
else
|
else
|
||||||
mrid.getName match {
|
mrid.getName match {
|
||||||
case name @ (CompilerID | LibraryID | ReflectID | ActorsID | ScalapID) if configQualifies && dependeeQualifies =>
|
case name @ (CompilerID | LibraryID | ReflectID | ActorsID | ScalapID)
|
||||||
ModuleRevisionId.newInstance(scalaOrganization, name, mrid.getBranch, scalaVersion, mrid.getQualifiedExtraAttributes)
|
if configQualifies && dependeeQualifies =>
|
||||||
|
ModuleRevisionId.newInstance(
|
||||||
|
scalaOrganization,
|
||||||
|
name,
|
||||||
|
mrid.getBranch,
|
||||||
|
scalaVersion,
|
||||||
|
mrid.getQualifiedExtraAttributes
|
||||||
|
)
|
||||||
case _ => mrid
|
case _ => mrid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -92,14 +130,32 @@ private[sbt] abstract class IvyScalaFunctions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def overrideScalaVersion(module: DefaultModuleDescriptor, organization: String, version: String, scalaVersionConfigs: Vector[String]): Unit = {
|
def overrideScalaVersion(
|
||||||
|
module: DefaultModuleDescriptor,
|
||||||
|
organization: String,
|
||||||
|
version: String,
|
||||||
|
scalaVersionConfigs: Vector[String]
|
||||||
|
): Unit = {
|
||||||
val mediator = new OverrideScalaMediator(organization, version, scalaVersionConfigs)
|
val mediator = new OverrideScalaMediator(organization, version, scalaVersionConfigs)
|
||||||
module.addDependencyDescriptorMediator(new ModuleId(Organization, "*"), ExactPatternMatcher.INSTANCE, mediator)
|
module.addDependencyDescriptorMediator(
|
||||||
|
new ModuleId(Organization, "*"),
|
||||||
|
ExactPatternMatcher.INSTANCE,
|
||||||
|
mediator
|
||||||
|
)
|
||||||
if (organization != Organization)
|
if (organization != Organization)
|
||||||
module.addDependencyDescriptorMediator(new ModuleId(organization, "*"), ExactPatternMatcher.INSTANCE, mediator)
|
module.addDependencyDescriptorMediator(
|
||||||
|
new ModuleId(organization, "*"),
|
||||||
|
ExactPatternMatcher.INSTANCE,
|
||||||
|
mediator
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
def overrideVersion(module: DefaultModuleDescriptor, org: String, name: String, version: String): Unit = {
|
def overrideVersion(
|
||||||
|
module: DefaultModuleDescriptor,
|
||||||
|
org: String,
|
||||||
|
name: String,
|
||||||
|
version: String
|
||||||
|
): Unit = {
|
||||||
val id = new ModuleId(org, name)
|
val id = new ModuleId(org, name)
|
||||||
val over = new OverrideDependencyDescriptorMediator(null, version)
|
val over = new OverrideDependencyDescriptorMediator(null, version)
|
||||||
module.addDependencyDescriptorMediator(id, ExactPatternMatcher.INSTANCE, over)
|
module.addDependencyDescriptorMediator(id, ExactPatternMatcher.INSTANCE, over)
|
||||||
|
|
@ -109,71 +165,98 @@ private[sbt] abstract class IvyScalaFunctions {
|
||||||
* Checks the immediate dependencies of module for dependencies on scala jars and verifies that the version on the
|
* Checks the immediate dependencies of module for dependencies on scala jars and verifies that the version on the
|
||||||
* dependencies matches scalaVersion.
|
* dependencies matches scalaVersion.
|
||||||
*/
|
*/
|
||||||
private def checkDependencies(module: ModuleDescriptor, scalaOrganization: String, scalaArtifacts: Vector[String], scalaBinaryVersion: String, scalaVersionConfigs0: Vector[String], log: Logger): Unit = {
|
private def checkDependencies(
|
||||||
val scalaVersionConfigs: String => Boolean = if (scalaVersionConfigs0.isEmpty) (c: String) => false else scalaVersionConfigs0.toSet
|
module: ModuleDescriptor,
|
||||||
def binaryScalaWarning(dep: DependencyDescriptor): Option[String] =
|
scalaOrganization: String,
|
||||||
{
|
scalaArtifacts: Vector[String],
|
||||||
val id = dep.getDependencyRevisionId
|
scalaBinaryVersion: String,
|
||||||
val depBinaryVersion = CrossVersion.binaryScalaVersion(id.getRevision)
|
scalaVersionConfigs0: Vector[String],
|
||||||
def isScalaLangOrg = id.getOrganisation == scalaOrganization
|
log: Logger
|
||||||
def isScalaArtifact = scalaArtifacts.contains(id.getName)
|
): Unit = {
|
||||||
def hasBinVerMismatch = depBinaryVersion != scalaBinaryVersion
|
val scalaVersionConfigs: String => Boolean =
|
||||||
def matchesOneOfTheConfigs = dep.getModuleConfigurations exists { scalaVersionConfigs }
|
if (scalaVersionConfigs0.isEmpty) (c: String) => false else scalaVersionConfigs0.toSet
|
||||||
val mismatched = isScalaLangOrg && isScalaArtifact && hasBinVerMismatch && matchesOneOfTheConfigs
|
def binaryScalaWarning(dep: DependencyDescriptor): Option[String] = {
|
||||||
if (mismatched)
|
val id = dep.getDependencyRevisionId
|
||||||
Some("Binary version (" + depBinaryVersion + ") for dependency " + id +
|
val depBinaryVersion = CrossVersion.binaryScalaVersion(id.getRevision)
|
||||||
|
def isScalaLangOrg = id.getOrganisation == scalaOrganization
|
||||||
|
def isScalaArtifact = scalaArtifacts.contains(id.getName)
|
||||||
|
def hasBinVerMismatch = depBinaryVersion != scalaBinaryVersion
|
||||||
|
def matchesOneOfTheConfigs = dep.getModuleConfigurations exists { scalaVersionConfigs }
|
||||||
|
val mismatched = isScalaLangOrg && isScalaArtifact && hasBinVerMismatch && matchesOneOfTheConfigs
|
||||||
|
if (mismatched)
|
||||||
|
Some(
|
||||||
|
"Binary version (" + depBinaryVersion + ") for dependency " + id +
|
||||||
"\n\tin " + module.getModuleRevisionId +
|
"\n\tin " + module.getModuleRevisionId +
|
||||||
" differs from Scala binary version in project (" + scalaBinaryVersion + ").")
|
" differs from Scala binary version in project (" + scalaBinaryVersion + ")."
|
||||||
else
|
)
|
||||||
None
|
else
|
||||||
}
|
None
|
||||||
module.getDependencies.toList.flatMap(binaryScalaWarning).toSet foreach { (s: String) => log.warn(s) }
|
}
|
||||||
|
module.getDependencies.toList.flatMap(binaryScalaWarning).toSet foreach { (s: String) =>
|
||||||
|
log.warn(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private def configurationSet(configurations: Iterable[Configuration]) = configurations.map(_.toString).toSet
|
private def configurationSet(configurations: Iterable[Configuration]) =
|
||||||
|
configurations.map(_.toString).toSet
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds exclusions for the scala library and compiler jars so that they are not downloaded. This is
|
* Adds exclusions for the scala library and compiler jars so that they are not downloaded. This is
|
||||||
* done because these jars are provided by the ScalaInstance of the project. The version of Scala to use
|
* done because these jars are provided by the ScalaInstance of the project. The version of Scala to use
|
||||||
* is done by setting scalaVersion in the project definition.
|
* is done by setting scalaVersion in the project definition.
|
||||||
*/
|
*/
|
||||||
private def excludeScalaJars(module: DefaultModuleDescriptor, configurations: Iterable[Configuration]): Unit = {
|
private def excludeScalaJars(
|
||||||
val configurationNames =
|
module: DefaultModuleDescriptor,
|
||||||
{
|
configurations: Iterable[Configuration]
|
||||||
val names = module.getConfigurationsNames
|
): Unit = {
|
||||||
if (configurations.isEmpty)
|
val configurationNames = {
|
||||||
names
|
val names = module.getConfigurationsNames
|
||||||
else {
|
if (configurations.isEmpty)
|
||||||
val configSet = configurationSet(configurations)
|
names
|
||||||
configSet.intersect(HashSet(names: _*))
|
else {
|
||||||
configSet.toArray
|
val configSet = configurationSet(configurations)
|
||||||
}
|
configSet.intersect(HashSet(names: _*))
|
||||||
|
configSet.toArray
|
||||||
}
|
}
|
||||||
|
}
|
||||||
def excludeScalaJar(name: String): Unit =
|
def excludeScalaJar(name: String): Unit =
|
||||||
module.addExcludeRule(excludeRule(Organization, name, configurationNames, "jar"))
|
module.addExcludeRule(excludeRule(Organization, name, configurationNames, "jar"))
|
||||||
excludeScalaJar(LibraryID)
|
excludeScalaJar(LibraryID)
|
||||||
excludeScalaJar(CompilerID)
|
excludeScalaJar(CompilerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an ExcludeRule that excludes artifacts with the given module organization and name for
|
* Creates an ExcludeRule that excludes artifacts with the given module organization and name for
|
||||||
* the given configurations.
|
* the given configurations.
|
||||||
*/
|
*/
|
||||||
private[sbt] def excludeRule(organization: String, name: String, configurationNames: Iterable[String], excludeTypePattern: String): ExcludeRule =
|
private[sbt] def excludeRule(
|
||||||
{
|
organization: String,
|
||||||
val artifact = new ArtifactId(ModuleId.newInstance(organization, name), "*", excludeTypePattern, "*")
|
name: String,
|
||||||
val rule = new DefaultExcludeRule(artifact, ExactPatternMatcher.INSTANCE, emptyMap[AnyRef, AnyRef])
|
configurationNames: Iterable[String],
|
||||||
configurationNames.foreach(rule.addConfiguration)
|
excludeTypePattern: String
|
||||||
rule
|
): ExcludeRule = {
|
||||||
}
|
val artifact =
|
||||||
|
new ArtifactId(ModuleId.newInstance(organization, name), "*", excludeTypePattern, "*")
|
||||||
|
val rule =
|
||||||
|
new DefaultExcludeRule(artifact, ExactPatternMatcher.INSTANCE, emptyMap[AnyRef, AnyRef])
|
||||||
|
configurationNames.foreach(rule.addConfiguration)
|
||||||
|
rule
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an IncludeRule that includes artifacts with the given module organization and name for
|
* Creates an IncludeRule that includes artifacts with the given module organization and name for
|
||||||
* the given configurations.
|
* the given configurations.
|
||||||
*/
|
*/
|
||||||
private[sbt] def includeRule(organization: String, name: String, configurationNames: Iterable[String], includeTypePattern: String): IncludeRule =
|
private[sbt] def includeRule(
|
||||||
{
|
organization: String,
|
||||||
val artifact = new ArtifactId(ModuleId.newInstance(organization, name), "*", includeTypePattern, "*")
|
name: String,
|
||||||
val rule = new DefaultIncludeRule(artifact, ExactPatternMatcher.INSTANCE, emptyMap[AnyRef, AnyRef])
|
configurationNames: Iterable[String],
|
||||||
configurationNames.foreach(rule.addConfiguration)
|
includeTypePattern: String
|
||||||
rule
|
): IncludeRule = {
|
||||||
}
|
val artifact =
|
||||||
|
new ArtifactId(ModuleId.newInstance(organization, name), "*", includeTypePattern, "*")
|
||||||
|
val rule =
|
||||||
|
new DefaultIncludeRule(artifact, ExactPatternMatcher.INSTANCE, emptyMap[AnyRef, AnyRef])
|
||||||
|
configurationNames.foreach(rule.addConfiguration)
|
||||||
|
rule
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,53 +24,56 @@ abstract class ModuleIDExtra {
|
||||||
def branchName: Option[String]
|
def branchName: Option[String]
|
||||||
|
|
||||||
protected[this] def copy(
|
protected[this] def copy(
|
||||||
organization: String = organization,
|
organization: String = organization,
|
||||||
name: String = name,
|
name: String = name,
|
||||||
revision: String = revision,
|
revision: String = revision,
|
||||||
configurations: Option[String] = configurations,
|
configurations: Option[String] = configurations,
|
||||||
isChanging: Boolean = isChanging,
|
isChanging: Boolean = isChanging,
|
||||||
isTransitive: Boolean = isTransitive,
|
isTransitive: Boolean = isTransitive,
|
||||||
isForce: Boolean = isForce,
|
isForce: Boolean = isForce,
|
||||||
explicitArtifacts: Vector[Artifact] = explicitArtifacts,
|
explicitArtifacts: Vector[Artifact] = explicitArtifacts,
|
||||||
inclusions: Vector[InclusionRule] = inclusions,
|
inclusions: Vector[InclusionRule] = inclusions,
|
||||||
exclusions: Vector[ExclusionRule] = exclusions,
|
exclusions: Vector[ExclusionRule] = exclusions,
|
||||||
extraAttributes: Map[String, String] = extraAttributes,
|
extraAttributes: Map[String, String] = extraAttributes,
|
||||||
crossVersion: CrossVersion = crossVersion,
|
crossVersion: CrossVersion = crossVersion,
|
||||||
branchName: Option[String] = branchName
|
branchName: Option[String] = branchName
|
||||||
): ModuleID
|
): ModuleID
|
||||||
|
|
||||||
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 = {
|
||||||
{
|
val buffer = ListBuffer.empty[String]
|
||||||
val buffer = ListBuffer.empty[String]
|
if (isChanging) {
|
||||||
if (isChanging) {
|
buffer += "changing"
|
||||||
buffer += "changing"
|
|
||||||
}
|
|
||||||
if (!isTransitive) {
|
|
||||||
buffer += "intransitive"
|
|
||||||
}
|
|
||||||
if (isForce) {
|
|
||||||
buffer += "force"
|
|
||||||
}
|
|
||||||
buffer.toList.mkString(";")
|
|
||||||
}
|
}
|
||||||
|
if (!isTransitive) {
|
||||||
|
buffer += "intransitive"
|
||||||
|
}
|
||||||
|
if (isForce) {
|
||||||
|
buffer += "force"
|
||||||
|
}
|
||||||
|
buffer.toList.mkString(";")
|
||||||
|
}
|
||||||
|
|
||||||
/** String representation of the extra attributes, excluding any information only attributes. */
|
/** String representation of the extra attributes, excluding any information only attributes. */
|
||||||
def extraString: String = extraDependencyAttributes.map { case (k, v) => k + "=" + v } mkString ("(", ", ", ")")
|
def extraString: String =
|
||||||
|
extraDependencyAttributes.map { case (k, v) => k + "=" + v } mkString ("(", ", ", ")")
|
||||||
|
|
||||||
/** Returns the extra attributes except for ones marked as information only (ones that typically would not be used for dependency resolution). */
|
/** Returns the extra attributes except for ones marked as information only (ones that typically would not be used for dependency resolution). */
|
||||||
def extraDependencyAttributes: Map[String, String] = extraAttributes.filterKeys(!_.startsWith(SbtPomExtraProperties.POM_INFO_KEY_PREFIX))
|
def extraDependencyAttributes: Map[String, String] =
|
||||||
|
extraAttributes.filterKeys(!_.startsWith(SbtPomExtraProperties.POM_INFO_KEY_PREFIX))
|
||||||
|
|
||||||
@deprecated("Use `cross(CrossVersion)`, the variant accepting a CrossVersion value constructed by a member of the CrossVersion object instead.", "0.12.0")
|
@deprecated(
|
||||||
|
"Use `cross(CrossVersion)`, the variant accepting a CrossVersion value constructed by a member of the CrossVersion object instead.",
|
||||||
|
"0.12.0"
|
||||||
|
)
|
||||||
def cross(v: Boolean): ModuleID = cross(if (v) CrossVersion.binary else Disabled())
|
def cross(v: Boolean): ModuleID = cross(if (v) CrossVersion.binary else Disabled())
|
||||||
|
|
||||||
/** Specifies the cross-version behavior for this module. See [CrossVersion] for details.*/
|
/** Specifies the cross-version behavior for this module. See [CrossVersion] for details.*/
|
||||||
|
|
@ -111,7 +114,8 @@ abstract class ModuleIDExtra {
|
||||||
* Declares the explicit artifacts for this module. If this ModuleID represents a dependency,
|
* Declares the explicit artifacts for this module. If this ModuleID represents a dependency,
|
||||||
* these artifact definitions override the information in the dependency's published metadata.
|
* these artifact definitions override the information in the dependency's published metadata.
|
||||||
*/
|
*/
|
||||||
def artifacts(newArtifacts: Artifact*) = copy(explicitArtifacts = newArtifacts.toVector ++ explicitArtifacts)
|
def artifacts(newArtifacts: Artifact*) =
|
||||||
|
copy(explicitArtifacts = newArtifacts.toVector ++ explicitArtifacts)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the provided exclusions to dependencies of this module. Note that only exclusions that specify
|
* Applies the provided exclusions to dependencies of this module. Note that only exclusions that specify
|
||||||
|
|
@ -120,13 +124,15 @@ abstract class ModuleIDExtra {
|
||||||
def excludeAll(rules: InclExclRule*) = copy(exclusions = this.exclusions ++ rules)
|
def excludeAll(rules: InclExclRule*) = copy(exclusions = this.exclusions ++ rules)
|
||||||
|
|
||||||
/** Excludes the dependency with organization `org` and `name` from being introduced by this dependency during resolution. */
|
/** Excludes the dependency with organization `org` and `name` from being introduced by this dependency during resolution. */
|
||||||
def exclude(org: String, name: String) = excludeAll(InclExclRule().withOrganization(org).withName(name))
|
def exclude(org: String, name: String) =
|
||||||
|
excludeAll(InclExclRule().withOrganization(org).withName(name))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds extra attributes for this module. All keys are prefixed with `e:` if they are not already so prefixed.
|
* Adds extra attributes for this module. All keys are prefixed with `e:` if they are not already so prefixed.
|
||||||
* This information will only be published in an ivy.xml and not in a pom.xml.
|
* This information will only be published in an ivy.xml and not in a pom.xml.
|
||||||
*/
|
*/
|
||||||
def extra(attributes: (String, String)*) = copy(extraAttributes = this.extraAttributes ++ ModuleID.checkE(attributes))
|
def extra(attributes: (String, String)*) =
|
||||||
|
copy(extraAttributes = this.extraAttributes ++ ModuleID.checkE(attributes))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not recommended for new use. This method is not deprecated, but the `update-classifiers` task is preferred
|
* Not recommended for new use. This method is not deprecated, but the `update-classifiers` task is preferred
|
||||||
|
|
@ -175,7 +181,9 @@ abstract class ModuleIDExtra {
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ModuleIDFunctions {
|
abstract class ModuleIDFunctions {
|
||||||
|
|
||||||
/** Prefixes all keys with `e:` if they are not already so prefixed. */
|
/** Prefixes all keys with `e:` if they are not already so prefixed. */
|
||||||
def checkE(attributes: Seq[(String, String)]) =
|
def checkE(attributes: Seq[(String, String)]) =
|
||||||
for ((key, value) <- attributes) yield if (key.startsWith("e:")) (key, value) else ("e:" + key, value)
|
for ((key, value) <- attributes)
|
||||||
|
yield if (key.startsWith("e:")) (key, value) else ("e:" + key, value)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,11 @@ final class RawRepository(val resolver: DependencyResolver) extends Resolver(res
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
override def hashCode: Int =
|
override def hashCode: Int = {
|
||||||
{
|
var hash = 1
|
||||||
var hash = 1
|
hash = hash * 31 + this.name.##
|
||||||
hash = hash * 31 + this.name.##
|
hash
|
||||||
hash
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class MavenRepositoryFunctions {
|
abstract class MavenRepositoryFunctions {
|
||||||
|
|
@ -37,11 +36,15 @@ abstract class PatternsFunctions {
|
||||||
def apply(artifactPatterns: String*): Patterns = Patterns(true, artifactPatterns: _*)
|
def apply(artifactPatterns: String*): Patterns = Patterns(true, artifactPatterns: _*)
|
||||||
def apply(isMavenCompatible: Boolean, artifactPatterns: String*): Patterns = {
|
def apply(isMavenCompatible: Boolean, artifactPatterns: String*): Patterns = {
|
||||||
val patterns = artifactPatterns.toVector
|
val patterns = artifactPatterns.toVector
|
||||||
Patterns().withIvyPatterns(patterns).withArtifactPatterns(patterns).withIsMavenCompatible(isMavenCompatible)
|
Patterns()
|
||||||
|
.withIvyPatterns(patterns)
|
||||||
|
.withArtifactPatterns(patterns)
|
||||||
|
.withIsMavenCompatible(isMavenCompatible)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait SshBasedRepositoryExtra {
|
trait SshBasedRepositoryExtra {
|
||||||
|
|
||||||
/** The object representing the configured ssh connection for this repository. */
|
/** The object representing the configured ssh connection for this repository. */
|
||||||
def connection: SshConnection
|
def connection: SshConnection
|
||||||
|
|
||||||
|
|
@ -53,11 +56,13 @@ trait SshBasedRepositoryExtra {
|
||||||
/** Configures this to use the specified user name and password when connecting to the remote repository. */
|
/** Configures this to use the specified user name and password when connecting to the remote repository. */
|
||||||
def as(user: String, password: String): RepositoryType = as(user, Some(password))
|
def as(user: String, password: String): RepositoryType = as(user, Some(password))
|
||||||
def as(user: String): RepositoryType = as(user, None)
|
def as(user: String): RepositoryType = as(user, None)
|
||||||
def as(user: String, password: Option[String]): RepositoryType = copy(PasswordAuthentication(user, password))
|
def as(user: String, password: Option[String]): RepositoryType =
|
||||||
|
copy(PasswordAuthentication(user, password))
|
||||||
|
|
||||||
/** Configures this to use the specified keyfile and password for the keyfile when connecting to the remote repository. */
|
/** Configures this to use the specified keyfile and password for the keyfile when connecting to the remote repository. */
|
||||||
def as(user: String, keyfile: File): RepositoryType = as(user, keyfile, None)
|
def as(user: String, keyfile: File): RepositoryType = as(user, keyfile, None)
|
||||||
def as(user: String, keyfile: File, password: String): RepositoryType = as(user, keyfile, Some(password))
|
def as(user: String, keyfile: File, password: String): RepositoryType =
|
||||||
|
as(user, keyfile, Some(password))
|
||||||
|
|
||||||
def as(user: String, keyfile: File, password: Option[String]): RepositoryType =
|
def as(user: String, keyfile: File, password: Option[String]): RepositoryType =
|
||||||
copy(KeyFileAuthentication(user, keyfile, password))
|
copy(KeyFileAuthentication(user, keyfile, password))
|
||||||
|
|
@ -80,7 +85,8 @@ trait SftpRepositoryExtra extends SshBasedRepositoryExtra {
|
||||||
|
|
||||||
type RepositoryType = SftpRepository
|
type RepositoryType = SftpRepository
|
||||||
|
|
||||||
protected def copy(connection: SshConnection): SftpRepository = SftpRepository(name, connection, patterns)
|
protected def copy(connection: SshConnection): SftpRepository =
|
||||||
|
SftpRepository(name, connection, patterns)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A repository that conforms to sbt launcher's interface */
|
/** A repository that conforms to sbt launcher's interface */
|
||||||
|
|
@ -96,7 +102,8 @@ trait ResolversSyntax {
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ResolverFunctions {
|
abstract class ResolverFunctions {
|
||||||
private[sbt] def useSecureResolvers = sys.props.get("sbt.repository.secure") map { _.toLowerCase == "true" } getOrElse true
|
private[sbt] def useSecureResolvers =
|
||||||
|
sys.props.get("sbt.repository.secure") map { _.toLowerCase == "true" } getOrElse true
|
||||||
|
|
||||||
val TypesafeRepositoryRoot = typesafeRepositoryRoot(useSecureResolvers)
|
val TypesafeRepositoryRoot = typesafeRepositoryRoot(useSecureResolvers)
|
||||||
val SbtRepositoryRoot = sbtRepositoryRoot(useSecureResolvers)
|
val SbtRepositoryRoot = sbtRepositoryRoot(useSecureResolvers)
|
||||||
|
|
@ -109,31 +116,49 @@ abstract class ResolverFunctions {
|
||||||
val JCenterRepositoryRoot = "https://jcenter.bintray.com/"
|
val JCenterRepositoryRoot = "https://jcenter.bintray.com/"
|
||||||
val DefaultMavenRepositoryRoot = "https://repo1.maven.org/maven2/"
|
val DefaultMavenRepositoryRoot = "https://repo1.maven.org/maven2/"
|
||||||
// TODO: This switch is only kept for backward compatibility. Hardcode to HTTPS in the future.
|
// TODO: This switch is only kept for backward compatibility. Hardcode to HTTPS in the future.
|
||||||
private[sbt] def centralRepositoryRoot(secure: Boolean) = (if (secure) "https" else "http") + "://repo1.maven.org/maven2/"
|
private[sbt] def centralRepositoryRoot(secure: Boolean) =
|
||||||
|
(if (secure) "https" else "http") + "://repo1.maven.org/maven2/"
|
||||||
// TODO: This switch is only kept for backward compatibility. Hardcode to HTTPS in the future.
|
// TODO: This switch is only kept for backward compatibility. Hardcode to HTTPS in the future.
|
||||||
private[sbt] def javanet2RepositoryRoot(secure: Boolean) =
|
private[sbt] def javanet2RepositoryRoot(secure: Boolean) =
|
||||||
if (secure) "https://maven.java.net/content/repositories/public/"
|
if (secure) "https://maven.java.net/content/repositories/public/"
|
||||||
else "http://download.java.net/maven/2"
|
else "http://download.java.net/maven/2"
|
||||||
// TODO: This switch is only kept for backward compatibility. Hardcode to HTTPS in the future.
|
// TODO: This switch is only kept for backward compatibility. Hardcode to HTTPS in the future.
|
||||||
private[sbt] def typesafeRepositoryRoot(secure: Boolean) = (if (secure) "https" else "http") + "://repo.typesafe.com/typesafe"
|
private[sbt] def typesafeRepositoryRoot(secure: Boolean) =
|
||||||
|
(if (secure) "https" else "http") + "://repo.typesafe.com/typesafe"
|
||||||
// TODO: This switch is only kept for backward compatibility. Hardcode to HTTPS in the future.
|
// TODO: This switch is only kept for backward compatibility. Hardcode to HTTPS in the future.
|
||||||
private[sbt] def sbtRepositoryRoot(secure: Boolean) = (if (secure) "https" else "http") + "://repo.scala-sbt.org/scalasbt"
|
private[sbt] def sbtRepositoryRoot(secure: Boolean) =
|
||||||
|
(if (secure) "https" else "http") + "://repo.scala-sbt.org/scalasbt"
|
||||||
|
|
||||||
// obsolete: kept only for launcher compatibility
|
// obsolete: kept only for launcher compatibility
|
||||||
private[sbt] val ScalaToolsReleasesName = "Sonatype OSS Releases"
|
private[sbt] val ScalaToolsReleasesName = "Sonatype OSS Releases"
|
||||||
private[sbt] val ScalaToolsSnapshotsName = "Sonatype OSS Snapshots"
|
private[sbt] val ScalaToolsSnapshotsName = "Sonatype OSS Snapshots"
|
||||||
private[sbt] val ScalaToolsReleasesRoot = SonatypeRepositoryRoot + "/releases"
|
private[sbt] val ScalaToolsReleasesRoot = SonatypeRepositoryRoot + "/releases"
|
||||||
private[sbt] val ScalaToolsSnapshotsRoot = SonatypeRepositoryRoot + "/snapshots"
|
private[sbt] val ScalaToolsSnapshotsRoot = SonatypeRepositoryRoot + "/snapshots"
|
||||||
private[sbt] val ScalaToolsReleases = MavenRepository(ScalaToolsReleasesName, ScalaToolsReleasesRoot)
|
private[sbt] val ScalaToolsReleases =
|
||||||
private[sbt] val ScalaToolsSnapshots = MavenRepository(ScalaToolsSnapshotsName, ScalaToolsSnapshotsRoot)
|
MavenRepository(ScalaToolsReleasesName, ScalaToolsReleasesRoot)
|
||||||
|
private[sbt] val ScalaToolsSnapshots =
|
||||||
|
MavenRepository(ScalaToolsSnapshotsName, ScalaToolsSnapshotsRoot)
|
||||||
|
|
||||||
def typesafeRepo(status: String) = MavenRepository("typesafe-" + status, TypesafeRepositoryRoot + "/" + status)
|
def typesafeRepo(status: String) =
|
||||||
def typesafeIvyRepo(status: String) = url("typesafe-ivy-" + status, new URL(TypesafeRepositoryRoot + "/ivy-" + status + "/"))(ivyStylePatterns)
|
MavenRepository("typesafe-" + status, TypesafeRepositoryRoot + "/" + status)
|
||||||
def sbtIvyRepo(status: String) = url(s"sbt-ivy-$status", new URL(s"$SbtRepositoryRoot/ivy-$status/"))(ivyStylePatterns)
|
def typesafeIvyRepo(status: String) =
|
||||||
def sbtPluginRepo(status: String) = url("sbt-plugin-" + status, new URL(SbtRepositoryRoot + "/sbt-plugin-" + status + "/"))(ivyStylePatterns)
|
url("typesafe-ivy-" + status, new URL(TypesafeRepositoryRoot + "/ivy-" + status + "/"))(
|
||||||
def sonatypeRepo(status: String) = MavenRepository("sonatype-" + status, SonatypeRepositoryRoot + "/" + status)
|
ivyStylePatterns
|
||||||
def bintrayRepo(owner: String, repo: String) = MavenRepository(s"bintray-$owner-$repo", s"https://dl.bintray.com/$owner/$repo/")
|
)
|
||||||
def bintrayIvyRepo(owner: String, repo: String) = url(s"bintray-$owner-$repo", new URL(s"https://dl.bintray.com/$owner/$repo/"))(Resolver.ivyStylePatterns)
|
def sbtIvyRepo(status: String) =
|
||||||
|
url(s"sbt-ivy-$status", new URL(s"$SbtRepositoryRoot/ivy-$status/"))(ivyStylePatterns)
|
||||||
|
def sbtPluginRepo(status: String) =
|
||||||
|
url("sbt-plugin-" + status, new URL(SbtRepositoryRoot + "/sbt-plugin-" + status + "/"))(
|
||||||
|
ivyStylePatterns
|
||||||
|
)
|
||||||
|
def sonatypeRepo(status: String) =
|
||||||
|
MavenRepository("sonatype-" + status, SonatypeRepositoryRoot + "/" + status)
|
||||||
|
def bintrayRepo(owner: String, repo: String) =
|
||||||
|
MavenRepository(s"bintray-$owner-$repo", s"https://dl.bintray.com/$owner/$repo/")
|
||||||
|
def bintrayIvyRepo(owner: String, repo: String) =
|
||||||
|
url(s"bintray-$owner-$repo", new URL(s"https://dl.bintray.com/$owner/$repo/"))(
|
||||||
|
Resolver.ivyStylePatterns
|
||||||
|
)
|
||||||
def jcenterRepo = JCenterRepository
|
def jcenterRepo = JCenterRepository
|
||||||
|
|
||||||
/** Add the local and Maven Central repositories to the user repositories. */
|
/** Add the local and Maven Central repositories to the user repositories. */
|
||||||
|
|
@ -152,7 +177,11 @@ abstract class ResolverFunctions {
|
||||||
* If `jcenter` is true, add the JCenter.
|
* If `jcenter` is true, add the JCenter.
|
||||||
* If `mavenCentral` is true, add the Maven Central repository.
|
* If `mavenCentral` is true, add the Maven Central repository.
|
||||||
*/
|
*/
|
||||||
def withDefaultResolvers(userResolvers: Seq[Resolver], jcenter: Boolean, mavenCentral: Boolean): Seq[Resolver] =
|
def withDefaultResolvers(
|
||||||
|
userResolvers: Seq[Resolver],
|
||||||
|
jcenter: Boolean,
|
||||||
|
mavenCentral: Boolean
|
||||||
|
): Seq[Resolver] =
|
||||||
Seq(Resolver.defaultLocal) ++
|
Seq(Resolver.defaultLocal) ++
|
||||||
userResolvers ++
|
userResolvers ++
|
||||||
single(JCenterRepository, jcenter) ++
|
single(JCenterRepository, jcenter) ++
|
||||||
|
|
@ -163,7 +192,11 @@ abstract class ResolverFunctions {
|
||||||
* If `jcenter` is true, add the JCenter.
|
* If `jcenter` is true, add the JCenter.
|
||||||
* If `mavenCentral` is true, add the Maven Central repository.
|
* If `mavenCentral` is true, add the Maven Central repository.
|
||||||
*/
|
*/
|
||||||
private[sbt] def reorganizeAppResolvers(appResolvers: Seq[Resolver], jcenter: Boolean, mavenCentral: Boolean): Seq[Resolver] =
|
private[sbt] def reorganizeAppResolvers(
|
||||||
|
appResolvers: Seq[Resolver],
|
||||||
|
jcenter: Boolean,
|
||||||
|
mavenCentral: Boolean
|
||||||
|
): Seq[Resolver] =
|
||||||
appResolvers.partition(_ == Resolver.defaultLocal) match {
|
appResolvers.partition(_ == Resolver.defaultLocal) match {
|
||||||
case (locals, xs) =>
|
case (locals, xs) =>
|
||||||
locals ++
|
locals ++
|
||||||
|
|
@ -181,78 +214,111 @@ abstract class ResolverFunctions {
|
||||||
|
|
||||||
/** 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 */
|
||||||
protected def construct(name: String, connection: SshConnection, patterns: Patterns): RepositoryType
|
protected def construct(
|
||||||
|
name: String,
|
||||||
|
connection: SshConnection,
|
||||||
|
patterns: Patterns
|
||||||
|
): RepositoryType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs this repository type with the given `name`. `basePatterns` are the initial patterns to use. A ManagedProject
|
* Constructs this repository type with the given `name`. `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.
|
* has an implicit defining these initial patterns based on a setting for either Maven or Ivy style patterns.
|
||||||
*/
|
*/
|
||||||
def apply(name: String)(implicit basePatterns: Patterns): RepositoryType =
|
def apply(name: String)(implicit basePatterns: Patterns): RepositoryType =
|
||||||
apply(name, None, None, None)
|
apply(name, None, None, None)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs this repository type with the given `name` and `hostname`. `basePatterns` are the initial patterns to use.
|
* Constructs this repository type with the given `name` and `hostname`. `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)(implicit basePatterns: Patterns): RepositoryType =
|
def apply(name: String, hostname: String)(implicit basePatterns: Patterns): RepositoryType =
|
||||||
apply(name, Some(hostname), None, None)
|
apply(name, Some(hostname), None, None)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs this repository type with the given `name`, `hostname`, and the `basePath` against which the initial
|
* Constructs this repository type with the given `name`, `hostname`, and the `basePath` against which the initial
|
||||||
* 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)(implicit basePatterns: Patterns): RepositoryType =
|
def apply(name: String, hostname: String, basePath: String)(
|
||||||
|
implicit basePatterns: Patterns
|
||||||
|
): RepositoryType =
|
||||||
apply(name, Some(hostname), None, Some(basePath))
|
apply(name, Some(hostname), None, Some(basePath))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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)(implicit basePatterns: Patterns): RepositoryType =
|
def apply(name: String, hostname: String, port: Int)(
|
||||||
|
implicit basePatterns: Patterns
|
||||||
|
): RepositoryType =
|
||||||
apply(name, Some(hostname), Some(port), None)
|
apply(name, Some(hostname), Some(port), None)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs this repository type with the given `name`, `hostname`, `port`, and the `basePath` against which the initial
|
* Constructs this repository type with the given `name`, `hostname`, `port`, and the `basePath` against which the initial
|
||||||
* 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)(implicit basePatterns: Patterns): RepositoryType =
|
def apply(name: String, hostname: String, port: Int, basePath: String)(
|
||||||
|
implicit basePatterns: Patterns
|
||||||
|
): RepositoryType =
|
||||||
apply(name, Some(hostname), Some(port), Some(basePath))
|
apply(name, Some(hostname), Some(port), Some(basePath))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs this repository type with the given `name`, `hostname`, `port`, and the `basePath` against which the initial
|
* Constructs this repository type with the given `name`, `hostname`, `port`, and the `basePath` against which the initial
|
||||||
* patterns will be resolved. `basePatterns` are the initial patterns to use. All but the `name` are optional (use None).
|
* patterns will be resolved. `basePatterns` are the initial patterns to use. All but the `name` are optional (use None).
|
||||||
* 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: Option[String], port: Option[Int], basePath: Option[String])(implicit basePatterns: Patterns): RepositoryType =
|
def apply(name: String, hostname: Option[String], port: Option[Int], basePath: Option[String])(
|
||||||
|
implicit basePatterns: Patterns
|
||||||
|
): RepositoryType =
|
||||||
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) = SshRepository(name, connection, patterns, None)
|
protected def construct(name: String, connection: SshConnection, patterns: Patterns) =
|
||||||
|
SshRepository(name, connection, patterns, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A factory to construct an interface to an Ivy SFTP resolver.*/
|
/** A factory to construct an interface to an Ivy SFTP resolver.*/
|
||||||
object sftp extends Define[SftpRepository] {
|
object sftp extends Define[SftpRepository] {
|
||||||
protected def construct(name: String, connection: SshConnection, patterns: Patterns) = SftpRepository(name, connection, patterns)
|
protected def construct(name: String, connection: SshConnection, patterns: Patterns) =
|
||||||
|
SftpRepository(name, connection, patterns)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A factory to construct an interface to an Ivy filesystem resolver. */
|
/** A factory to construct an interface to an Ivy filesystem resolver. */
|
||||||
object file {
|
object file {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a file resolver with the given name. The patterns to use must be explicitly specified
|
* Constructs a file resolver with the given name. The patterns to use must be explicitly specified
|
||||||
* using the `ivys` or `artifacts` methods on the constructed resolver object.
|
* using the `ivys` or `artifacts` methods on the constructed resolver object.
|
||||||
*/
|
*/
|
||||||
def apply(name: String): FileRepository = FileRepository(name, defaultFileConfiguration, Patterns(false))
|
def apply(name: String): FileRepository =
|
||||||
|
FileRepository(name, defaultFileConfiguration, Patterns(false))
|
||||||
|
|
||||||
/** Constructs a file resolver with the given name and base directory. */
|
/** Constructs a file resolver with the given name and base directory. */
|
||||||
def apply(name: String, baseDirectory: File)(implicit basePatterns: Patterns): FileRepository =
|
def apply(name: String, baseDirectory: File)(implicit basePatterns: Patterns): FileRepository =
|
||||||
baseRepository(new File(baseDirectory.toURI.normalize).getAbsolutePath)(FileRepository(name, defaultFileConfiguration, _))
|
baseRepository(new File(baseDirectory.toURI.normalize).getAbsolutePath)(
|
||||||
|
FileRepository(name, defaultFileConfiguration, _)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
object url {
|
object url {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a URL resolver with the given name. The patterns to use must be explicitly specified
|
* Constructs a URL resolver with the given name. The patterns to use must be explicitly specified
|
||||||
* using the `ivys` or `artifacts` methods on the constructed resolver object.
|
* using the `ivys` or `artifacts` methods on the constructed resolver object.
|
||||||
*/
|
*/
|
||||||
def apply(name: String): URLRepository = URLRepository(name, Patterns(false))
|
def apply(name: String): URLRepository = URLRepository(name, Patterns(false))
|
||||||
|
|
||||||
/** Constructs a file resolver with the given name and base directory. */
|
/** Constructs a file resolver with the given name and base directory. */
|
||||||
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)(implicit basePatterns: Patterns): T =
|
private def baseRepository[T](base: String)(construct: Patterns => T)(
|
||||||
|
implicit basePatterns: Patterns
|
||||||
|
): T =
|
||||||
construct(resolvePatterns(base, basePatterns))
|
construct(resolvePatterns(base, basePatterns))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -264,41 +330,53 @@ abstract class ResolverFunctions {
|
||||||
case Some(path) => resolvePatterns(path, patterns)
|
case Some(path) => resolvePatterns(path, patterns)
|
||||||
case None => patterns
|
case None => patterns
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Resolves the ivy file and artifact patterns in `patterns` against the given base. */
|
/** Resolves the ivy file and artifact patterns in `patterns` against the given base. */
|
||||||
private def resolvePatterns(base: String, basePatterns: Patterns): Patterns =
|
private def resolvePatterns(base: String, basePatterns: Patterns): Patterns = {
|
||||||
{
|
def resolveAll(patterns: Vector[String]) = patterns.map(p => resolvePattern(base, p))
|
||||||
def resolveAll(patterns: Vector[String]) = patterns.map(p => resolvePattern(base, p))
|
Patterns(
|
||||||
Patterns(resolveAll(basePatterns.ivyPatterns), resolveAll(basePatterns.artifactPatterns), basePatterns.isMavenCompatible, basePatterns.descriptorOptional, basePatterns.skipConsistencyCheck)
|
resolveAll(basePatterns.ivyPatterns),
|
||||||
}
|
resolveAll(basePatterns.artifactPatterns),
|
||||||
private[sbt] def resolvePattern(base: String, pattern: String): String =
|
basePatterns.isMavenCompatible,
|
||||||
{
|
basePatterns.descriptorOptional,
|
||||||
val normBase = base.replace('\\', '/')
|
basePatterns.skipConsistencyCheck
|
||||||
if (normBase.endsWith("/") || pattern.startsWith("/")) normBase + pattern else normBase + "/" + pattern
|
)
|
||||||
}
|
}
|
||||||
|
private[sbt] def resolvePattern(base: String, pattern: String): String = {
|
||||||
|
val normBase = base.replace('\\', '/')
|
||||||
|
if (normBase.endsWith("/") || pattern.startsWith("/")) normBase + pattern
|
||||||
|
else normBase + "/" + pattern
|
||||||
|
}
|
||||||
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 = "[organisation]/[module](_[scalaVersion])(_[sbtVersion])/[revision]/[artifact]-[revision](-[classifier]).[ext]"
|
def mavenStyleBasePattern =
|
||||||
def localBasePattern = "[organisation]/[module]/" + PluginPattern + "(/[branch])/[revision]/[type]s/[artifact](-[classifier]).[ext]"
|
"[organisation]/[module](_[scalaVersion])(_[sbtVersion])/[revision]/[artifact]-[revision](-[classifier]).[ext]"
|
||||||
def defaultRetrievePattern = "[type]s/[organisation]/[module]/" + PluginPattern + "[artifact](-[revision])(-[classifier]).[ext]"
|
def localBasePattern =
|
||||||
|
"[organisation]/[module]/" + PluginPattern + "(/[branch])/[revision]/[type]s/[artifact](-[classifier]).[ext]"
|
||||||
|
def defaultRetrievePattern =
|
||||||
|
"[type]s/[organisation]/[module]/" + PluginPattern + "[artifact](-[revision])(-[classifier]).[ext]"
|
||||||
final val PluginPattern = "(scala_[scalaVersion]/)(sbt_[sbtVersion]/)"
|
final val PluginPattern = "(scala_[scalaVersion]/)(sbt_[sbtVersion]/)"
|
||||||
private[this] def mavenLocalDir: File = {
|
private[this] def mavenLocalDir: File = {
|
||||||
def loadHomeFromSettings(f: () => File): Option[File] =
|
def loadHomeFromSettings(f: () => File): Option[File] =
|
||||||
try {
|
try {
|
||||||
val file = f()
|
val file = f()
|
||||||
if (!file.exists) None
|
if (!file.exists) None
|
||||||
else ((XML.loadFile(file) \ "localRepository").text match {
|
else
|
||||||
case "" => None
|
((XML.loadFile(file) \ "localRepository").text match {
|
||||||
case e @ _ => Some(new File(e))
|
case "" => None
|
||||||
})
|
case e @ _ => Some(new File(e))
|
||||||
|
})
|
||||||
} catch {
|
} catch {
|
||||||
// Occurs inside File constructor when property or environment variable does not exist
|
// Occurs inside File constructor when property or environment variable does not exist
|
||||||
case _: NullPointerException => None
|
case _: NullPointerException => None
|
||||||
// Occurs when File does not exist
|
// Occurs when File does not exist
|
||||||
case _: IOException => None
|
case _: IOException => None
|
||||||
case e: SAXParseException => System.err.println(s"WARNING: Problem parsing ${f().getAbsolutePath}, ${e.getMessage}"); None
|
case e: SAXParseException =>
|
||||||
|
System.err.println(s"WARNING: Problem parsing ${f().getAbsolutePath}, ${e.getMessage}");
|
||||||
|
None
|
||||||
}
|
}
|
||||||
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
|
||||||
|
|
@ -309,14 +387,16 @@ abstract class ResolverFunctions {
|
||||||
def mavenLocal: MavenRepository = new MavenCache("Maven2 Local", mavenLocalDir)
|
def mavenLocal: MavenRepository = new MavenCache("Maven2 Local", mavenLocalDir)
|
||||||
def defaultLocal = defaultUserFileRepository("local")
|
def defaultLocal = defaultUserFileRepository("local")
|
||||||
def defaultShared = defaultUserFileRepository("shared")
|
def defaultShared = defaultUserFileRepository("shared")
|
||||||
def defaultUserFileRepository(id: String) =
|
def defaultUserFileRepository(id: String) = {
|
||||||
{
|
val pList = Vector(s"$${ivy.home}/$id/$localBasePattern")
|
||||||
val pList = Vector(s"$${ivy.home}/$id/$localBasePattern")
|
FileRepository(
|
||||||
FileRepository(id, defaultFileConfiguration, Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false))
|
id,
|
||||||
}
|
defaultFileConfiguration,
|
||||||
def defaultIvyPatterns =
|
|
||||||
{
|
|
||||||
val pList = Vector(localBasePattern)
|
|
||||||
Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false)
|
Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false)
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
def defaultIvyPatterns = {
|
||||||
|
val pList = Vector(localBasePattern)
|
||||||
|
Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,11 @@ import java.io.File
|
||||||
* and for obtaining references to a selected subset of the underlying files.
|
* and for obtaining references to a selected subset of the underlying files.
|
||||||
*/
|
*/
|
||||||
final class RichUpdateReport(report: UpdateReport) {
|
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.map(f => (f, f.lastModified)).toMap
|
||||||
val stamps = files.map(f => (f, f.lastModified)).toMap
|
UpdateReport(report.cachedDescriptor, report.configurations, report.stats, stamps)
|
||||||
UpdateReport(report.cachedDescriptor, report.configurations, report.stats, stamps)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
import DependencyFilter._
|
import DependencyFilter._
|
||||||
|
|
||||||
|
|
@ -24,12 +23,19 @@ final class RichUpdateReport(report: UpdateReport) {
|
||||||
def matching(f: DependencyFilter): Vector[File] = select0(f).distinct
|
def matching(f: DependencyFilter): Vector[File] = select0(f).distinct
|
||||||
|
|
||||||
/** Obtains all successfully retrieved files matching all provided filters. */
|
/** Obtains all successfully retrieved files matching all provided filters. */
|
||||||
def select(configuration: ConfigurationFilter, module: ModuleFilter, artifact: ArtifactFilter): Vector[File] =
|
def select(
|
||||||
|
configuration: ConfigurationFilter,
|
||||||
|
module: ModuleFilter,
|
||||||
|
artifact: ArtifactFilter
|
||||||
|
): Vector[File] =
|
||||||
matching(DependencyFilter.make(configuration, module, artifact))
|
matching(DependencyFilter.make(configuration, module, artifact))
|
||||||
|
|
||||||
def select(configuration: ConfigurationFilter): Vector[File] = select(configuration, moduleFilter(), artifactFilter())
|
def select(configuration: ConfigurationFilter): Vector[File] =
|
||||||
def select(module: ModuleFilter): Vector[File] = select(configurationFilter(), module, artifactFilter())
|
select(configuration, moduleFilter(), artifactFilter())
|
||||||
def select(artifact: ArtifactFilter): Vector[File] = select(configurationFilter(), moduleFilter(), artifact)
|
def select(module: ModuleFilter): Vector[File] =
|
||||||
|
select(configurationFilter(), module, artifactFilter())
|
||||||
|
def select(artifact: ArtifactFilter): Vector[File] =
|
||||||
|
select(configurationFilter(), moduleFilter(), artifact)
|
||||||
|
|
||||||
private[this] def select0(f: DependencyFilter): Vector[File] =
|
private[this] def select0(f: DependencyFilter): Vector[File] =
|
||||||
for {
|
for {
|
||||||
|
|
@ -39,7 +45,9 @@ final class RichUpdateReport(report: UpdateReport) {
|
||||||
if f(cReport.configuration, mReport.module, artifact)
|
if f(cReport.configuration, mReport.module, artifact)
|
||||||
} yield {
|
} yield {
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
sys.error(s"Null file: conf=${cReport.configuration}, module=${mReport.module}, art: $artifact")
|
sys.error(
|
||||||
|
s"Null file: conf=${cReport.configuration}, module=${mReport.module}, art: $artifact"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
file
|
file
|
||||||
}
|
}
|
||||||
|
|
@ -49,14 +57,20 @@ final class RichUpdateReport(report: UpdateReport) {
|
||||||
moduleReportMap { (configuration, modReport) =>
|
moduleReportMap { (configuration, modReport) =>
|
||||||
modReport
|
modReport
|
||||||
.withArtifacts(
|
.withArtifacts(
|
||||||
modReport.artifacts filter { case (art, file) => f(configuration, modReport.module, art) }
|
modReport.artifacts filter {
|
||||||
|
case (art, file) => f(configuration, modReport.module, art)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
.withMissingArtifacts(
|
.withMissingArtifacts(
|
||||||
modReport.missingArtifacts filter { art => f(configuration, modReport.module, art) }
|
modReport.missingArtifacts filter { art =>
|
||||||
|
f(configuration, modReport.module, art)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def substitute(f: (String, ModuleID, Vector[(Artifact, File)]) => Vector[(Artifact, File)]): UpdateReport =
|
private[sbt] def substitute(
|
||||||
|
f: (String, ModuleID, Vector[(Artifact, File)]) => Vector[(Artifact, File)]
|
||||||
|
): UpdateReport =
|
||||||
moduleReportMap { (configuration, modReport) =>
|
moduleReportMap { (configuration, modReport) =>
|
||||||
val newArtifacts = f(configuration, modReport.module, modReport.artifacts)
|
val newArtifacts = f(configuration, modReport.module, modReport.artifacts)
|
||||||
modReport
|
modReport
|
||||||
|
|
@ -85,13 +99,14 @@ final class RichUpdateReport(report: UpdateReport) {
|
||||||
.withMissingArtifacts((modReport.missingArtifacts ++ f(modReport.module)).distinct)
|
.withMissingArtifacts((modReport.missingArtifacts ++ f(modReport.module)).distinct)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def moduleReportMap(f: (String, ModuleReport) => ModuleReport): UpdateReport =
|
private[sbt] def moduleReportMap(f: (String, ModuleReport) => ModuleReport): UpdateReport = {
|
||||||
{
|
val newConfigurations = report.configurations.map { confReport =>
|
||||||
val newConfigurations = report.configurations.map { confReport =>
|
import confReport._
|
||||||
import confReport._
|
val newModules = modules map { modReport =>
|
||||||
val newModules = modules map { modReport => f(configuration, modReport) }
|
f(configuration, modReport)
|
||||||
ConfigurationReport(configuration, newModules, details)
|
|
||||||
}
|
}
|
||||||
UpdateReport(report.cachedDescriptor, newConfigurations, report.stats, report.stamps)
|
ConfigurationReport(configuration, newModules, details)
|
||||||
}
|
}
|
||||||
|
UpdateReport(report.cachedDescriptor, newConfigurations, report.stats, report.stamps)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,20 +12,22 @@ import sbt.util.Logger
|
||||||
* See also UpdateConfiguration in IvyActions.scala.
|
* See also UpdateConfiguration in IvyActions.scala.
|
||||||
*/
|
*/
|
||||||
final class UpdateOptions private[sbt] (
|
final class UpdateOptions private[sbt] (
|
||||||
// If set to CircularDependencyLevel.Error, halt the dependency resolution.
|
// If set to CircularDependencyLevel.Error, halt the dependency resolution.
|
||||||
val circularDependencyLevel: CircularDependencyLevel,
|
val circularDependencyLevel: CircularDependencyLevel,
|
||||||
// If set to true, prioritize inter-project resolver
|
// If set to true, prioritize inter-project resolver
|
||||||
val interProjectFirst: Boolean,
|
val interProjectFirst: Boolean,
|
||||||
// If set to true, check all resolvers for snapshots.
|
// If set to true, check all resolvers for snapshots.
|
||||||
val latestSnapshots: Boolean,
|
val latestSnapshots: Boolean,
|
||||||
// If set to true, use consolidated resolution.
|
// If set to true, use consolidated resolution.
|
||||||
val consolidatedResolution: Boolean,
|
val consolidatedResolution: Boolean,
|
||||||
// If set to true, use cached resolution.
|
// If set to true, use cached resolution.
|
||||||
val cachedResolution: Boolean,
|
val cachedResolution: Boolean,
|
||||||
// Extension point for an alternative resolver converter.
|
// Extension point for an alternative resolver converter.
|
||||||
val resolverConverter: UpdateOptions.ResolverConverter
|
val resolverConverter: UpdateOptions.ResolverConverter
|
||||||
) {
|
) {
|
||||||
def withCircularDependencyLevel(circularDependencyLevel: CircularDependencyLevel): UpdateOptions =
|
def withCircularDependencyLevel(
|
||||||
|
circularDependencyLevel: CircularDependencyLevel
|
||||||
|
): UpdateOptions =
|
||||||
copy(circularDependencyLevel = circularDependencyLevel)
|
copy(circularDependencyLevel = circularDependencyLevel)
|
||||||
def withInterProjectFirst(interProjectFirst: Boolean): UpdateOptions =
|
def withInterProjectFirst(interProjectFirst: Boolean): UpdateOptions =
|
||||||
copy(interProjectFirst = interProjectFirst)
|
copy(interProjectFirst = interProjectFirst)
|
||||||
|
|
@ -42,17 +44,18 @@ final class UpdateOptions private[sbt] (
|
||||||
cachedResolution = cachedResoluton,
|
cachedResolution = cachedResoluton,
|
||||||
consolidatedResolution = cachedResolution
|
consolidatedResolution = cachedResolution
|
||||||
)
|
)
|
||||||
|
|
||||||
/** Extention point for an alternative resolver converter. */
|
/** Extention point for an alternative resolver converter. */
|
||||||
def withResolverConverter(resolverConverter: UpdateOptions.ResolverConverter): UpdateOptions =
|
def withResolverConverter(resolverConverter: UpdateOptions.ResolverConverter): UpdateOptions =
|
||||||
copy(resolverConverter = resolverConverter)
|
copy(resolverConverter = resolverConverter)
|
||||||
|
|
||||||
private[sbt] def copy(
|
private[sbt] def copy(
|
||||||
circularDependencyLevel: CircularDependencyLevel = this.circularDependencyLevel,
|
circularDependencyLevel: CircularDependencyLevel = this.circularDependencyLevel,
|
||||||
interProjectFirst: Boolean = this.interProjectFirst,
|
interProjectFirst: Boolean = this.interProjectFirst,
|
||||||
latestSnapshots: Boolean = this.latestSnapshots,
|
latestSnapshots: Boolean = this.latestSnapshots,
|
||||||
consolidatedResolution: Boolean = this.consolidatedResolution,
|
consolidatedResolution: Boolean = this.consolidatedResolution,
|
||||||
cachedResolution: Boolean = this.cachedResolution,
|
cachedResolution: Boolean = this.cachedResolution,
|
||||||
resolverConverter: UpdateOptions.ResolverConverter = this.resolverConverter
|
resolverConverter: UpdateOptions.ResolverConverter = this.resolverConverter
|
||||||
): UpdateOptions =
|
): UpdateOptions =
|
||||||
new UpdateOptions(
|
new UpdateOptions(
|
||||||
circularDependencyLevel,
|
circularDependencyLevel,
|
||||||
|
|
@ -73,16 +76,15 @@ final class UpdateOptions private[sbt] (
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
override def hashCode: Int =
|
override def hashCode: Int = {
|
||||||
{
|
var hash = 1
|
||||||
var hash = 1
|
hash = hash * 31 + this.circularDependencyLevel.##
|
||||||
hash = hash * 31 + this.circularDependencyLevel.##
|
hash = hash * 31 + this.interProjectFirst.##
|
||||||
hash = hash * 31 + this.interProjectFirst.##
|
hash = hash * 31 + this.latestSnapshots.##
|
||||||
hash = hash * 31 + this.latestSnapshots.##
|
hash = hash * 31 + this.cachedResolution.##
|
||||||
hash = hash * 31 + this.cachedResolution.##
|
hash = hash * 31 + this.resolverConverter.##
|
||||||
hash = hash * 31 + this.resolverConverter.##
|
hash
|
||||||
hash
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object UpdateOptions {
|
object UpdateOptions {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,9 @@ abstract class ConfigurationReportExtra {
|
||||||
}
|
}
|
||||||
|
|
||||||
def retrieve(f: (String, ModuleID, Artifact, File) => File): ConfigurationReport =
|
def retrieve(f: (String, ModuleID, Artifact, File) => File): ConfigurationReport =
|
||||||
ConfigurationReport(configuration, modules map { _.retrieve((mid, art, file) => f(configuration, mid, art, file)) }, details)
|
ConfigurationReport(configuration, modules map {
|
||||||
|
_.retrieve((mid, art, file) => f(configuration, mid, art, file))
|
||||||
|
}, details)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ModuleReportExtra {
|
abstract class ModuleReportExtra {
|
||||||
|
|
@ -52,7 +54,8 @@ abstract class ModuleReportExtra {
|
||||||
def licenses: Vector[(String, Option[String])]
|
def licenses: Vector[(String, Option[String])]
|
||||||
def callers: Vector[Caller]
|
def callers: Vector[Caller]
|
||||||
|
|
||||||
protected[this] def arts: Vector[String] = artifacts.map(_.toString) ++ missingArtifacts.map(art => "(MISSING) " + art)
|
protected[this] def arts: Vector[String] =
|
||||||
|
artifacts.map(_.toString) ++ missingArtifacts.map(art => "(MISSING) " + art)
|
||||||
|
|
||||||
def detailReport: String =
|
def detailReport: String =
|
||||||
s"\t\t- ${module.revision}\n" +
|
s"\t\t- ${module.revision}\n" +
|
||||||
|
|
@ -71,48 +74,50 @@ abstract class ModuleReportExtra {
|
||||||
if (extraAttributes.isEmpty) None
|
if (extraAttributes.isEmpty) None
|
||||||
else { Some(extraAttributes.toString) }
|
else { Some(extraAttributes.toString) }
|
||||||
) +
|
) +
|
||||||
reportStr("isDefault", isDefault map { _.toString }) +
|
reportStr("isDefault", isDefault map { _.toString }) +
|
||||||
reportStr("branch", branch) +
|
reportStr("branch", branch) +
|
||||||
reportStr(
|
reportStr(
|
||||||
"configurations",
|
"configurations",
|
||||||
if (configurations.isEmpty) None
|
if (configurations.isEmpty) None
|
||||||
else { Some(configurations.mkString(", ")) }
|
else { Some(configurations.mkString(", ")) }
|
||||||
) +
|
) +
|
||||||
reportStr(
|
reportStr(
|
||||||
"licenses",
|
"licenses",
|
||||||
if (licenses.isEmpty) None
|
if (licenses.isEmpty) None
|
||||||
else { Some(licenses.mkString(", ")) }
|
else { Some(licenses.mkString(", ")) }
|
||||||
) +
|
) +
|
||||||
reportStr(
|
reportStr(
|
||||||
"callers",
|
"callers",
|
||||||
if (callers.isEmpty) None
|
if (callers.isEmpty) None
|
||||||
else { Some(callers.mkString(", ")) }
|
else { Some(callers.mkString(", ")) }
|
||||||
)
|
)
|
||||||
private[sbt] def reportStr(key: String, value: Option[String]): String =
|
private[sbt] def reportStr(key: String, value: Option[String]): String =
|
||||||
value map { x => s"\t\t\t$key: $x\n" } getOrElse ""
|
value map { x =>
|
||||||
|
s"\t\t\t$key: $x\n"
|
||||||
|
} getOrElse ""
|
||||||
|
|
||||||
def retrieve(f: (ModuleID, Artifact, File) => File): ModuleReport =
|
def retrieve(f: (ModuleID, Artifact, File) => File): ModuleReport =
|
||||||
copy(artifacts = artifacts.map { case (art, file) => (art, f(module, art, file)) })
|
copy(artifacts = artifacts.map { case (art, file) => (art, f(module, art, file)) })
|
||||||
|
|
||||||
protected[this] def copy(
|
protected[this] def copy(
|
||||||
module: ModuleID = module,
|
module: ModuleID = module,
|
||||||
artifacts: Vector[(Artifact, File)] = artifacts,
|
artifacts: Vector[(Artifact, File)] = artifacts,
|
||||||
missingArtifacts: Vector[Artifact] = missingArtifacts,
|
missingArtifacts: Vector[Artifact] = missingArtifacts,
|
||||||
status: Option[String] = status,
|
status: Option[String] = status,
|
||||||
publicationDate: Option[ju.Calendar] = publicationDate,
|
publicationDate: Option[ju.Calendar] = publicationDate,
|
||||||
resolver: Option[String] = resolver,
|
resolver: Option[String] = resolver,
|
||||||
artifactResolver: Option[String] = artifactResolver,
|
artifactResolver: Option[String] = artifactResolver,
|
||||||
evicted: Boolean = evicted,
|
evicted: Boolean = evicted,
|
||||||
evictedData: Option[String] = evictedData,
|
evictedData: Option[String] = evictedData,
|
||||||
evictedReason: Option[String] = evictedReason,
|
evictedReason: Option[String] = evictedReason,
|
||||||
problem: Option[String] = problem,
|
problem: Option[String] = problem,
|
||||||
homepage: Option[String] = homepage,
|
homepage: Option[String] = homepage,
|
||||||
extraAttributes: Map[String, String] = extraAttributes,
|
extraAttributes: Map[String, String] = extraAttributes,
|
||||||
isDefault: Option[Boolean] = isDefault,
|
isDefault: Option[Boolean] = isDefault,
|
||||||
branch: Option[String] = branch,
|
branch: Option[String] = branch,
|
||||||
configurations: Vector[String] = configurations,
|
configurations: Vector[String] = configurations,
|
||||||
licenses: Vector[(String, Option[String])] = licenses,
|
licenses: Vector[(String, Option[String])] = licenses,
|
||||||
callers: Vector[Caller] = callers
|
callers: Vector[Caller] = callers
|
||||||
): ModuleReport
|
): ModuleReport
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,22 +128,21 @@ abstract class UpdateReportExtra {
|
||||||
private[sbt] def stamps: Map[File, Long]
|
private[sbt] def stamps: Map[File, Long]
|
||||||
|
|
||||||
/** 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 (k, v) =>
|
||||||
case (k, 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: (String, ModuleID, Artifact, File) => File): UpdateReport =
|
def retrieve(f: (String, ModuleID, Artifact, File) => File): UpdateReport =
|
||||||
UpdateReport(cachedDescriptor, configurations map { _ retrieve f }, stats, stamps)
|
UpdateReport(cachedDescriptor, configurations map { _ retrieve f }, stats, stamps)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package sbt.librarymanagement
|
package sbt.librarymanagement
|
||||||
|
|
||||||
final class VersionNumber private[sbt] (
|
final class VersionNumber private[sbt] (
|
||||||
val numbers: Seq[Long],
|
val numbers: Seq[Long],
|
||||||
val tags: Seq[String],
|
val tags: Seq[String],
|
||||||
val extras: Seq[String]
|
val extras: Seq[String]
|
||||||
) {
|
) {
|
||||||
def _1: Option[Long] = get(0)
|
def _1: Option[Long] = get(0)
|
||||||
def _2: Option[Long] = get(1)
|
def _2: Option[Long] = get(1)
|
||||||
|
|
@ -33,12 +33,14 @@ final class VersionNumber private[sbt] (
|
||||||
extras.hashCode
|
extras.hashCode
|
||||||
override def equals(o: Any): Boolean =
|
override def equals(o: Any): Boolean =
|
||||||
o match {
|
o match {
|
||||||
case v: VersionNumber => (this.numbers == v.numbers) && (this.tags == v.tags) && (this.extras == v.extras)
|
case v: VersionNumber =>
|
||||||
case _ => false
|
(this.numbers == v.numbers) && (this.tags == v.tags) && (this.extras == v.extras)
|
||||||
|
case _ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object VersionNumber {
|
object VersionNumber {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param numbers numbers delimited by a dot.
|
* @param numbers numbers delimited by a dot.
|
||||||
* @param tags string prefixed by a dash.
|
* @param tags string prefixed by a dash.
|
||||||
|
|
@ -74,10 +76,11 @@ object VersionNumber {
|
||||||
val TaggedVersion = """(\d{1,14})([\.\d{1,14}]*)((?:-\w+)*)((?:\+.+)*)""".r
|
val TaggedVersion = """(\d{1,14})([\.\d{1,14}]*)((?:-\w+)*)((?:\+.+)*)""".r
|
||||||
val NonSpaceString = """(\S+)""".r
|
val NonSpaceString = """(\S+)""".r
|
||||||
v match {
|
v match {
|
||||||
case TaggedVersion(m, ns, ts, es) => Some((Vector(m.toLong) ++ splitDot(ns), splitDash(ts), splitPlus(es)))
|
case TaggedVersion(m, ns, ts, es) =>
|
||||||
case "" => None
|
Some((Vector(m.toLong) ++ splitDot(ns), splitDash(ts), splitPlus(es)))
|
||||||
case NonSpaceString(s) => Some((Vector(), Vector(), Vector(s)))
|
case "" => None
|
||||||
case _ => None
|
case NonSpaceString(s) => Some((Vector(), Vector(), Vector(s)))
|
||||||
|
case _ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,8 +101,18 @@ object VersionNumber {
|
||||||
doIsCompat(v1, v2) || doIsCompat(v2, v1)
|
doIsCompat(v1, v2) || doIsCompat(v2, v1)
|
||||||
private[this] def doIsCompat(v1: VersionNumber, v2: VersionNumber): Boolean =
|
private[this] def doIsCompat(v1: VersionNumber, v2: VersionNumber): Boolean =
|
||||||
(v1, v2) match {
|
(v1, v2) match {
|
||||||
case (v1, v2) if (v1.size >= 2) && (v2.size >= 2) => // A normal version number MUST take the form X.Y.Z
|
case (v1, v2)
|
||||||
(v1._1.get, v1._2.get, v1._3.getOrElse(0L), v1.tags, v2._1.get, v2._2.get, v2._3.getOrElse(0L), v2.tags) match {
|
if (v1.size >= 2) && (v2.size >= 2) => // A normal version number MUST take the form X.Y.Z
|
||||||
|
(
|
||||||
|
v1._1.get,
|
||||||
|
v1._2.get,
|
||||||
|
v1._3.getOrElse(0L),
|
||||||
|
v1.tags,
|
||||||
|
v2._1.get,
|
||||||
|
v2._2.get,
|
||||||
|
v2._3.getOrElse(0L),
|
||||||
|
v2.tags
|
||||||
|
) match {
|
||||||
case (0L, _, _, _, 0L, _, _, _) =>
|
case (0L, _, _, _, 0L, _, _, _) =>
|
||||||
// Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.
|
// Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.
|
||||||
equalsIgnoreExtra(v1, v2)
|
equalsIgnoreExtra(v1, v2)
|
||||||
|
|
@ -107,8 +120,8 @@ object VersionNumber {
|
||||||
// A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers
|
// A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers
|
||||||
equalsIgnoreExtra(v1, v2)
|
equalsIgnoreExtra(v1, v2)
|
||||||
case (x1, _, _, _, x2, _, _, _) =>
|
case (x1, _, _, _, x2, _, _, _) =>
|
||||||
// Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible bug fixes are introduced.
|
// Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible bug fixes are introduced.
|
||||||
// Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards compatible functionality is introduced
|
// Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards compatible functionality is introduced
|
||||||
x1 == x2
|
x1 == x2
|
||||||
case _ => equalsIgnoreExtra(v1, v2)
|
case _ => equalsIgnoreExtra(v1, v2)
|
||||||
}
|
}
|
||||||
|
|
@ -129,13 +142,14 @@ object VersionNumber {
|
||||||
doIsCompat(v1, v2) || doIsCompat(v2, v1)
|
doIsCompat(v1, v2) || doIsCompat(v2, v1)
|
||||||
private[this] def doIsCompat(v1: VersionNumber, v2: VersionNumber): Boolean =
|
private[this] def doIsCompat(v1: VersionNumber, v2: VersionNumber): Boolean =
|
||||||
(v1, v2) match {
|
(v1, v2) match {
|
||||||
case (v1, v2) if (v1.size >= 3) && (v2.size >= 3) => // A normal version number MUST take the form X.Y.Z
|
case (v1, v2)
|
||||||
|
if (v1.size >= 3) && (v2.size >= 3) => // A normal version number MUST take the form X.Y.Z
|
||||||
(v1._1.get, v1._2.get, v1._3.get, v1.tags, v2._1.get, v2._2.get, v2._3.get, v2.tags) match {
|
(v1._1.get, v1._2.get, v1._3.get, v1.tags, v2._1.get, v2._2.get, v2._3.get, v2.tags) match {
|
||||||
case (x1, y1, 0, ts1, x2, y2, 0, ts2) if ts1.nonEmpty || ts2.nonEmpty =>
|
case (x1, y1, 0, ts1, x2, y2, 0, ts2) if ts1.nonEmpty || ts2.nonEmpty =>
|
||||||
// A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers
|
// A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers
|
||||||
equalsIgnoreExtra(v1, v2)
|
equalsIgnoreExtra(v1, v2)
|
||||||
case (x1, y1, _, _, x2, y2, _, _) =>
|
case (x1, y1, _, _, x2, y2, _, _) =>
|
||||||
// Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible changes are introduced.
|
// Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible changes are introduced.
|
||||||
(x1 == x2) && (y1 == y2)
|
(x1 == x2) && (y1 == y2)
|
||||||
case _ => equalsIgnoreExtra(v1, v2)
|
case _ => equalsIgnoreExtra(v1, v2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,17 @@ trait BaseIvySpecification extends UnitSpec {
|
||||||
def currentTarget: File = currentBase / "target" / "ivyhome"
|
def currentTarget: File = currentBase / "target" / "ivyhome"
|
||||||
def currentManaged: File = currentBase / "target" / "lib_managed"
|
def currentManaged: File = currentBase / "target" / "lib_managed"
|
||||||
def currentDependency: File = currentBase / "target" / "dependency"
|
def currentDependency: File = currentBase / "target" / "dependency"
|
||||||
def defaultModuleId: ModuleID = ModuleID("com.example", "foo", "0.1.0").withConfigurations(Some("compile"))
|
def defaultModuleId: ModuleID =
|
||||||
|
ModuleID("com.example", "foo", "0.1.0").withConfigurations(Some("compile"))
|
||||||
|
|
||||||
lazy val log = ConsoleLogger()
|
lazy val log = ConsoleLogger()
|
||||||
|
|
||||||
def configurations = Vector(Compile, Test, Runtime)
|
def configurations = Vector(Compile, Test, Runtime)
|
||||||
def module(moduleId: ModuleID, deps: Vector[ModuleID], scalaFullVersion: Option[String],
|
def module(moduleId: ModuleID,
|
||||||
uo: UpdateOptions = UpdateOptions(), overrideScalaVersion: Boolean = true): IvySbt#Module = {
|
deps: Vector[ModuleID],
|
||||||
|
scalaFullVersion: Option[String],
|
||||||
|
uo: UpdateOptions = UpdateOptions(),
|
||||||
|
overrideScalaVersion: Boolean = true): IvySbt#Module = {
|
||||||
val ivyScala = scalaFullVersion map { fv =>
|
val ivyScala = scalaFullVersion map { fv =>
|
||||||
IvyScala(
|
IvyScala(
|
||||||
scalaFullVersion = fv,
|
scalaFullVersion = fv,
|
||||||
|
|
@ -53,23 +57,42 @@ trait BaseIvySpecification extends UnitSpec {
|
||||||
val off = false
|
val off = false
|
||||||
val check = Vector.empty
|
val check = Vector.empty
|
||||||
val resCacheDir = currentTarget / "resolution-cache"
|
val resCacheDir = currentTarget / "resolution-cache"
|
||||||
new InlineIvyConfiguration(paths, resolvers, other, moduleConfs, off, None, check, Some(resCacheDir), uo, log)
|
new InlineIvyConfiguration(paths,
|
||||||
|
resolvers,
|
||||||
|
other,
|
||||||
|
moduleConfs,
|
||||||
|
off,
|
||||||
|
None,
|
||||||
|
check,
|
||||||
|
Some(resCacheDir),
|
||||||
|
uo,
|
||||||
|
log)
|
||||||
}
|
}
|
||||||
|
|
||||||
def makeUpdateConfiguration: UpdateConfiguration = {
|
def makeUpdateConfiguration: UpdateConfiguration = {
|
||||||
val retrieveConfig = RetrieveConfiguration(currentManaged, Resolver.defaultRetrievePattern).withSync(false)
|
val retrieveConfig =
|
||||||
UpdateConfiguration(Some(retrieveConfig), false, UpdateLogging.Full, ArtifactTypeFilter.forbid(Set("src", "doc")))
|
RetrieveConfiguration(currentManaged, Resolver.defaultRetrievePattern).withSync(false)
|
||||||
|
UpdateConfiguration(Some(retrieveConfig),
|
||||||
|
false,
|
||||||
|
UpdateLogging.Full,
|
||||||
|
ArtifactTypeFilter.forbid(Set("src", "doc")))
|
||||||
}
|
}
|
||||||
|
|
||||||
def ivyUpdateEither(module: IvySbt#Module): Either[UnresolvedWarning, UpdateReport] = {
|
def ivyUpdateEither(module: IvySbt#Module): Either[UnresolvedWarning, UpdateReport] = {
|
||||||
// IO.delete(currentTarget)
|
// IO.delete(currentTarget)
|
||||||
val config = makeUpdateConfiguration
|
val config = makeUpdateConfiguration
|
||||||
IvyActions.updateEither(module, config, UnresolvedWarningConfiguration(), LogicalClock.unknown, Some(currentDependency), log)
|
IvyActions.updateEither(module,
|
||||||
|
config,
|
||||||
|
UnresolvedWarningConfiguration(),
|
||||||
|
LogicalClock.unknown,
|
||||||
|
Some(currentDependency),
|
||||||
|
log)
|
||||||
}
|
}
|
||||||
|
|
||||||
def cleanIvyCache(): Unit = IO.delete(currentTarget / "cache")
|
def cleanIvyCache(): Unit = IO.delete(currentTarget / "cache")
|
||||||
|
|
||||||
def cleanCachedResolutionCache(module: IvySbt#Module): Unit = IvyActions.cleanCachedResolutionCache(module, log)
|
def cleanCachedResolutionCache(module: IvySbt#Module): Unit =
|
||||||
|
IvyActions.cleanCachedResolutionCache(module, log)
|
||||||
|
|
||||||
def ivyUpdate(module: IvySbt#Module) =
|
def ivyUpdate(module: IvySbt#Module) =
|
||||||
ivyUpdateEither(module) match {
|
ivyUpdateEither(module) match {
|
||||||
|
|
@ -78,7 +101,8 @@ trait BaseIvySpecification extends UnitSpec {
|
||||||
throw w.resolveException
|
throw w.resolveException
|
||||||
}
|
}
|
||||||
|
|
||||||
def mkPublishConfiguration(resolver: Resolver, artifacts: Map[Artifact, File]): PublishConfiguration = {
|
def mkPublishConfiguration(resolver: Resolver,
|
||||||
|
artifacts: Map[Artifact, File]): PublishConfiguration = {
|
||||||
new PublishConfiguration(
|
new PublishConfiguration(
|
||||||
ivyFile = None,
|
ivyFile = None,
|
||||||
resolverName = resolver.name,
|
resolverName = resolver.name,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@ class CachedResolutionSpec extends BaseIvySpecification {
|
||||||
cleanIvyCache()
|
cleanIvyCache()
|
||||||
val m = module(
|
val m = module(
|
||||||
ModuleID("com.example", "foo", "0.1.0").withConfigurations(Some("compile")),
|
ModuleID("com.example", "foo", "0.1.0").withConfigurations(Some("compile")),
|
||||||
Vector(commonsIo13), Some("2.10.2"), UpdateOptions().withCachedResolution(true)
|
Vector(commonsIo13),
|
||||||
|
Some("2.10.2"),
|
||||||
|
UpdateOptions().withCachedResolution(true)
|
||||||
)
|
)
|
||||||
val report = ivyUpdate(m)
|
val report = ivyUpdate(m)
|
||||||
cleanCachedResolutionCache(m)
|
cleanCachedResolutionCache(m)
|
||||||
|
|
@ -26,7 +28,9 @@ class CachedResolutionSpec extends BaseIvySpecification {
|
||||||
// log.setLevel(Level.Debug)
|
// log.setLevel(Level.Debug)
|
||||||
val m = module(
|
val m = module(
|
||||||
ModuleID("com.example", "foo", "0.2.0").withConfigurations(Some("compile")),
|
ModuleID("com.example", "foo", "0.2.0").withConfigurations(Some("compile")),
|
||||||
Vector(mavenCayennePlugin302), Some("2.10.2"), UpdateOptions().withCachedResolution(true)
|
Vector(mavenCayennePlugin302),
|
||||||
|
Some("2.10.2"),
|
||||||
|
UpdateOptions().withCachedResolution(true)
|
||||||
)
|
)
|
||||||
ivyUpdateEither(m) match {
|
ivyUpdateEither(m) match {
|
||||||
case Right(_) => sys.error("this should've failed")
|
case Right(_) => sys.error("this should've failed")
|
||||||
|
|
@ -37,10 +41,10 @@ class CachedResolutionSpec extends BaseIvySpecification {
|
||||||
case Right(_) => sys.error("this should've failed 2")
|
case Right(_) => sys.error("this should've failed 2")
|
||||||
case Left(uw) =>
|
case Left(uw) =>
|
||||||
uw.lines should contain allOf ("\n\tNote: Unresolved dependencies path:",
|
uw.lines should contain allOf ("\n\tNote: Unresolved dependencies path:",
|
||||||
"\t\tfoundrylogic.vpp:vpp:2.2.1",
|
"\t\tfoundrylogic.vpp:vpp:2.2.1",
|
||||||
"\t\t +- org.apache.cayenne:cayenne-tools:3.0.2",
|
"\t\t +- org.apache.cayenne:cayenne-tools:3.0.2",
|
||||||
"\t\t +- org.apache.cayenne.plugins:maven-cayenne-plugin:3.0.2",
|
"\t\t +- org.apache.cayenne.plugins:maven-cayenne-plugin:3.0.2",
|
||||||
"\t\t +- com.example:foo:0.2.0")
|
"\t\t +- com.example:foo:0.2.0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,7 +58,8 @@ class CachedResolutionSpec extends BaseIvySpecification {
|
||||||
val m = module(
|
val m = module(
|
||||||
ModuleID("com.example", "foo", "0.3.0").withConfigurations(Some("compile")),
|
ModuleID("com.example", "foo", "0.3.0").withConfigurations(Some("compile")),
|
||||||
Vector(avro177, dataAvro1940, netty320),
|
Vector(avro177, dataAvro1940, netty320),
|
||||||
Some("2.10.2"), UpdateOptions().withCachedResolution(true)
|
Some("2.10.2"),
|
||||||
|
UpdateOptions().withCachedResolution(true)
|
||||||
)
|
)
|
||||||
// first resolution creates the minigraph
|
// first resolution creates the minigraph
|
||||||
val _ = ivyUpdate(m)
|
val _ = ivyUpdate(m)
|
||||||
|
|
@ -62,15 +67,23 @@ class CachedResolutionSpec extends BaseIvySpecification {
|
||||||
// second resolution reads from the minigraph
|
// second resolution reads from the minigraph
|
||||||
val report = ivyUpdate(m)
|
val report = ivyUpdate(m)
|
||||||
val modules: Seq[String] = report.configurations.head.modules map { _.toString }
|
val modules: Seq[String] = report.configurations.head.modules map { _.toString }
|
||||||
assert(modules exists { x: String => x contains """org.jboss.netty:netty:3.2.0.Final""" })
|
assert(modules exists { x: String =>
|
||||||
assert(!(modules exists { x: String => x contains """org.jboss.netty:netty:3.2.1.Final""" }))
|
x contains """org.jboss.netty:netty:3.2.0.Final"""
|
||||||
|
})
|
||||||
|
assert(!(modules exists { x: String =>
|
||||||
|
x contains """org.jboss.netty:netty:3.2.1.Final"""
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
def commonsIo13 = ModuleID("commons-io", "commons-io", "1.3").withConfigurations(Some("compile"))
|
def commonsIo13 = ModuleID("commons-io", "commons-io", "1.3").withConfigurations(Some("compile"))
|
||||||
def mavenCayennePlugin302 = ModuleID("org.apache.cayenne.plugins", "maven-cayenne-plugin", "3.0.2").withConfigurations(Some("compile"))
|
def mavenCayennePlugin302 =
|
||||||
|
ModuleID("org.apache.cayenne.plugins", "maven-cayenne-plugin", "3.0.2").withConfigurations(
|
||||||
|
Some("compile"))
|
||||||
def avro177 = ModuleID("org.apache.avro", "avro", "1.7.7").withConfigurations(Some("compile"))
|
def avro177 = ModuleID("org.apache.avro", "avro", "1.7.7").withConfigurations(Some("compile"))
|
||||||
def dataAvro1940 = ModuleID("com.linkedin.pegasus", "data-avro", "1.9.40").withConfigurations(Some("compile"))
|
def dataAvro1940 =
|
||||||
def netty320 = ModuleID("org.jboss.netty", "netty", "3.2.0.Final").withConfigurations(Some("compile"))
|
ModuleID("com.linkedin.pegasus", "data-avro", "1.9.40").withConfigurations(Some("compile"))
|
||||||
|
def netty320 =
|
||||||
|
ModuleID("org.jboss.netty", "netty", "3.2.0.Final").withConfigurations(Some("compile"))
|
||||||
|
|
||||||
def defaultOptions = EvictionWarningOptions.default
|
def defaultOptions = EvictionWarningOptions.default
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,11 +73,16 @@ class ComponentManagerTest extends UnitSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
private def checksum(files: Iterable[File]): Seq[String] = files.map(checksum).toSeq
|
private def checksum(files: Iterable[File]): Seq[String] = files.map(checksum).toSeq
|
||||||
private def checksum(file: File): String = if (file.exists) ChecksumHelper.computeAsString(file, "sha1") else ""
|
private def checksum(file: File): String =
|
||||||
private def defineFile(manager: ComponentManager, id: String, name: String): String = createFile(manager, id, name)(checksum)
|
if (file.exists) ChecksumHelper.computeAsString(file, "sha1") else ""
|
||||||
private def defineFiles(manager: ComponentManager, id: String, names: String*): Seq[String] = createFiles(manager, id, names: _*)(checksum)
|
private def defineFile(manager: ComponentManager, id: String, name: String): String =
|
||||||
private def createFile[T](manager: ComponentManager, id: String, name: String)(f: File => T): T = createFiles(manager, id, name)(files => f(files.toList.head))
|
createFile(manager, id, name)(checksum)
|
||||||
private def createFiles[T](manager: ComponentManager, id: String, names: String*)(f: Seq[File] => T): T =
|
private def defineFiles(manager: ComponentManager, id: String, names: String*): Seq[String] =
|
||||||
|
createFiles(manager, id, names: _*)(checksum)
|
||||||
|
private def createFile[T](manager: ComponentManager, id: String, name: String)(f: File => T): T =
|
||||||
|
createFiles(manager, id, name)(files => f(files.toList.head))
|
||||||
|
private def createFiles[T](manager: ComponentManager, id: String, names: String*)(
|
||||||
|
f: Seq[File] => T): T =
|
||||||
withTemporaryDirectory { dir =>
|
withTemporaryDirectory { dir =>
|
||||||
val files = names.map(name => new File(dir, name))
|
val files = names.map(name => new File(dir, name))
|
||||||
files.foreach(writeRandomContent)
|
files.foreach(writeRandomContent)
|
||||||
|
|
@ -87,7 +92,9 @@ class ComponentManagerTest extends UnitSpec {
|
||||||
private def writeRandomContent(file: File) = IO.write(file, randomString)
|
private def writeRandomContent(file: File) = IO.write(file, randomString)
|
||||||
private def randomString = "asdf"
|
private def randomString = "asdf"
|
||||||
private def withManager[T](f: ComponentManager => T): T =
|
private def withManager[T](f: ComponentManager => T): T =
|
||||||
withTemporaryDirectory { ivyHome => withManagerHome(ivyHome)(f) }
|
withTemporaryDirectory { ivyHome =>
|
||||||
|
withManagerHome(ivyHome)(f)
|
||||||
|
}
|
||||||
|
|
||||||
private def withManagerHome[T](ivyHome: File)(f: ComponentManager => T): T =
|
private def withManagerHome[T](ivyHome: File)(f: ComponentManager => T): T =
|
||||||
TestLogger { logger =>
|
TestLogger { logger =>
|
||||||
|
|
@ -105,19 +112,26 @@ class ComponentManagerTest extends UnitSpec {
|
||||||
override def defineComponent(id: String, files: Array[File]): Unit = {
|
override def defineComponent(id: String, files: Array[File]): Unit = {
|
||||||
val location = componentLocation(id)
|
val location = componentLocation(id)
|
||||||
if (location.exists)
|
if (location.exists)
|
||||||
throw new RuntimeException(s"Cannot redefine component. ID: $id, files: ${files.mkString(",")}")
|
throw new RuntimeException(
|
||||||
|
s"Cannot redefine component. ID: $id, files: ${files.mkString(",")}")
|
||||||
else {
|
else {
|
||||||
IO.copy(files.map { f => f -> new java.io.File(location, f.getName) })
|
IO.copy(files.map { f =>
|
||||||
|
f -> new java.io.File(location, f.getName)
|
||||||
|
})
|
||||||
()
|
()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override def addToComponent(id: String, files: Array[File]): Boolean = {
|
override def addToComponent(id: String, files: Array[File]): Boolean = {
|
||||||
val location = componentLocation(id)
|
val location = componentLocation(id)
|
||||||
IO.copy(files.map { f => f -> new java.io.File(location, f.getName) })
|
IO.copy(files.map { f =>
|
||||||
|
f -> new java.io.File(location, f.getName)
|
||||||
|
})
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
override def component(id: String): Array[File] =
|
override def component(id: String): Array[File] =
|
||||||
Option(componentLocation(id).listFiles()).map(_.filter(_.isFile)).getOrElse(Array.empty)
|
Option(componentLocation(id).listFiles())
|
||||||
|
.map(_.filter(_.isFile))
|
||||||
|
.getOrElse(Array.empty)
|
||||||
}
|
}
|
||||||
// A stubbed locking API.
|
// A stubbed locking API.
|
||||||
object locks extends xsbti.GlobalLock {
|
object locks extends xsbti.GlobalLock {
|
||||||
|
|
|
||||||
|
|
@ -118,22 +118,28 @@ class CrossVersionTest extends UnitSpec {
|
||||||
CrossVersion.binaryScalaVersion("2.20170314093845.0-87654321") shouldBe "2.20170314093845.0-87654321"
|
CrossVersion.binaryScalaVersion("2.20170314093845.0-87654321") shouldBe "2.20170314093845.0-87654321"
|
||||||
}
|
}
|
||||||
it should "return patch Scala version for 2.11.8 as 2.11.8" in {
|
it should "return patch Scala version for 2.11.8 as 2.11.8" in {
|
||||||
CrossVersion(CrossVersion.patch, "2.11.8", "dummy").map(_("artefact")) shouldBe Some("artefact_2.11.8")
|
CrossVersion(CrossVersion.patch, "2.11.8", "dummy").map(_("artefact")) shouldBe Some(
|
||||||
|
"artefact_2.11.8")
|
||||||
}
|
}
|
||||||
it should "return patch Scala version for 2.11.8-M1 as 2.11.8-M1" in {
|
it should "return patch Scala version for 2.11.8-M1 as 2.11.8-M1" in {
|
||||||
CrossVersion(CrossVersion.patch, "2.11.8-M1", "dummy").map(_("artefact")) shouldBe Some("artefact_2.11.8-M1")
|
CrossVersion(CrossVersion.patch, "2.11.8-M1", "dummy").map(_("artefact")) shouldBe Some(
|
||||||
|
"artefact_2.11.8-M1")
|
||||||
}
|
}
|
||||||
it should "return patch Scala version for 2.11.8-RC1 as 2.11.8-RC1" in {
|
it should "return patch Scala version for 2.11.8-RC1 as 2.11.8-RC1" in {
|
||||||
CrossVersion(CrossVersion.patch, "2.11.8-RC1", "dummy").map(_("artefact")) shouldBe Some("artefact_2.11.8-RC1")
|
CrossVersion(CrossVersion.patch, "2.11.8-RC1", "dummy").map(_("artefact")) shouldBe Some(
|
||||||
|
"artefact_2.11.8-RC1")
|
||||||
}
|
}
|
||||||
it should "return patch Scala version for 2.11.8-bin-extra as 2.11.8" in {
|
it should "return patch Scala version for 2.11.8-bin-extra as 2.11.8" in {
|
||||||
CrossVersion(CrossVersion.patch, "2.11.8-bin-extra", "dummy").map(_("artefact")) shouldBe Some("artefact_2.11.8")
|
CrossVersion(CrossVersion.patch, "2.11.8-bin-extra", "dummy").map(_("artefact")) shouldBe Some(
|
||||||
|
"artefact_2.11.8")
|
||||||
}
|
}
|
||||||
it should "return patch Scala version for 2.11.8-M1-bin-extra as 2.11.8-M1" in {
|
it should "return patch Scala version for 2.11.8-M1-bin-extra as 2.11.8-M1" in {
|
||||||
CrossVersion(CrossVersion.patch, "2.11.8-M1-bin-extra", "dummy").map(_("artefact")) shouldBe Some("artefact_2.11.8-M1")
|
CrossVersion(CrossVersion.patch, "2.11.8-M1-bin-extra", "dummy")
|
||||||
|
.map(_("artefact")) shouldBe Some("artefact_2.11.8-M1")
|
||||||
}
|
}
|
||||||
it should "return patch Scala version for 2.11.8-RC1-bin-extra as 2.11.8-RC1" in {
|
it should "return patch Scala version for 2.11.8-RC1-bin-extra as 2.11.8-RC1" in {
|
||||||
CrossVersion(CrossVersion.patch, "2.11.8-RC1-bin-extra", "dummy").map(_("artefact")) shouldBe Some("artefact_2.11.8-RC1")
|
CrossVersion(CrossVersion.patch, "2.11.8-RC1-bin-extra", "dummy")
|
||||||
|
.map(_("artefact")) shouldBe Some("artefact_2.11.8-RC1")
|
||||||
}
|
}
|
||||||
it should "return disabled cross version as equal to a copy" in {
|
it should "return disabled cross version as equal to a copy" in {
|
||||||
Disabled() shouldBe Disabled()
|
Disabled() shouldBe Disabled()
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,16 @@ class CustomPomParserTest extends UnitSpec {
|
||||||
val repoUrl = getClass.getResource("/test-maven-repo")
|
val repoUrl = getClass.getResource("/test-maven-repo")
|
||||||
val local = MavenRepository("Test Repo", repoUrl.toExternalForm)
|
val local = MavenRepository("Test Repo", repoUrl.toExternalForm)
|
||||||
val paths = IvyPaths(new File("."), Some(cacheDir))
|
val paths = IvyPaths(new File("."), Some(cacheDir))
|
||||||
val conf = new InlineIvyConfiguration(paths, Vector(local), Vector.empty, Vector.empty, false, None, Vector("sha1", "md5"), None, UpdateOptions(), log)
|
val conf = new InlineIvyConfiguration(paths,
|
||||||
|
Vector(local),
|
||||||
|
Vector.empty,
|
||||||
|
Vector.empty,
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
Vector("sha1", "md5"),
|
||||||
|
None,
|
||||||
|
UpdateOptions(),
|
||||||
|
log)
|
||||||
val ivySbt = new IvySbt(conf)
|
val ivySbt = new IvySbt(conf)
|
||||||
val resolveOpts = new ResolveOptions().setConfs(Array("default"))
|
val resolveOpts = new ResolveOptions().setConfs(Array("default"))
|
||||||
val mrid = ModuleRevisionId.newInstance("com.test", "test-artifact", "1.0.0-SNAPSHOT")
|
val mrid = ModuleRevisionId.newInstance("com.test", "test-artifact", "1.0.0-SNAPSHOT")
|
||||||
|
|
@ -26,7 +35,8 @@ class CustomPomParserTest extends UnitSpec {
|
||||||
|
|
||||||
resolveReport.hasError shouldBe false
|
resolveReport.hasError shouldBe false
|
||||||
resolveReport.getArtifacts.size() shouldBe 1
|
resolveReport.getArtifacts.size() shouldBe 1
|
||||||
val artifact: IvyArtifact = resolveReport.getArtifacts.asInstanceOf[java.util.List[IvyArtifact]].get(0)
|
val artifact: IvyArtifact =
|
||||||
|
resolveReport.getArtifacts.asInstanceOf[java.util.List[IvyArtifact]].get(0)
|
||||||
artifact.getModuleRevisionId shouldBe mrid
|
artifact.getModuleRevisionId shouldBe mrid
|
||||||
artifact.getExt shouldBe "jar"
|
artifact.getExt shouldBe "jar"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,11 +52,14 @@ class DMSerializationSpec extends UnitSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy val updateReportExample =
|
lazy val updateReportExample =
|
||||||
UpdateReport(new File("./foo"), Vector(configurationReportExample),
|
UpdateReport(new File("./foo"),
|
||||||
UpdateStats(0, 0, 0, false), Map(new File("./foo") -> 0))
|
Vector(configurationReportExample),
|
||||||
|
UpdateStats(0, 0, 0, false),
|
||||||
|
Map(new File("./foo") -> 0))
|
||||||
lazy val configurationReportExample =
|
lazy val configurationReportExample =
|
||||||
ConfigurationReport("compile", Vector(moduleReportExample),
|
ConfigurationReport("compile",
|
||||||
Vector(organizationArtifactReportExample))
|
Vector(moduleReportExample),
|
||||||
|
Vector(organizationArtifactReportExample))
|
||||||
lazy val organizationArtifactReportExample =
|
lazy val organizationArtifactReportExample =
|
||||||
OrganizationArtifactReport("org", "name", Vector(moduleReportExample))
|
OrganizationArtifactReport("org", "name", Vector(moduleReportExample))
|
||||||
lazy val moduleReportExample =
|
lazy val moduleReportExample =
|
||||||
|
|
@ -68,13 +71,13 @@ class DMSerializationSpec extends UnitSpec {
|
||||||
def roundtripStr[A: JsonReader: JsonWriter](a: A): Assertion =
|
def roundtripStr[A: JsonReader: JsonWriter](a: A): Assertion =
|
||||||
roundtripBuilder(a) { _.toString shouldBe _.toString }
|
roundtripBuilder(a) { _.toString shouldBe _.toString }
|
||||||
|
|
||||||
def roundtripBuilder[A: JsonReader: JsonWriter](a: A)(f: (A, A) => Assertion): Assertion =
|
def roundtripBuilder[A: JsonReader: JsonWriter](a: A)(f: (A, A) => Assertion): Assertion = {
|
||||||
{
|
val json = isoString to (Converter toJsonUnsafe a)
|
||||||
val json = isoString to (Converter toJsonUnsafe a)
|
println(json)
|
||||||
println(json)
|
val obj = Converter fromJsonUnsafe [A] (isoString from json)
|
||||||
val obj = Converter fromJsonUnsafe[A] (isoString from json)
|
f(a, obj)
|
||||||
f(a, obj)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
implicit val isoString: IsoString[JValue] = IsoString.iso(CompactPrinter.apply, FixedParser.parseUnsafe)
|
implicit val isoString: IsoString[JValue] =
|
||||||
|
IsoString.iso(CompactPrinter.apply, FixedParser.parseUnsafe)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,19 +44,29 @@ class EvictionWarningSpec extends BaseIvySpecification {
|
||||||
it should "be detected if it's enabled" in scalaLibTransitiveWarn2()
|
it should "be detected if it's enabled" in scalaLibTransitiveWarn2()
|
||||||
it should "print out message about the eviction if it's enabled" in scalaLibTransitiveWarn3()
|
it should "print out message about the eviction if it's enabled" in scalaLibTransitiveWarn3()
|
||||||
|
|
||||||
def akkaActor214 = ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(Some("compile")) cross CrossVersion.binary
|
def akkaActor214 =
|
||||||
def akkaActor230 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("compile")) cross CrossVersion.binary
|
ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(Some("compile")) cross CrossVersion.binary
|
||||||
def akkaActor234 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.4").withConfigurations(Some("compile")) cross CrossVersion.binary
|
def akkaActor230 =
|
||||||
def scala2102 = ModuleID("org.scala-lang", "scala-library", "2.10.2").withConfigurations(Some("compile"))
|
ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("compile")) cross CrossVersion.binary
|
||||||
def scala2103 = ModuleID("org.scala-lang", "scala-library", "2.10.3").withConfigurations(Some("compile"))
|
def akkaActor234 =
|
||||||
def scala2104 = ModuleID("org.scala-lang", "scala-library", "2.10.4").withConfigurations(Some("compile"))
|
ModuleID("com.typesafe.akka", "akka-actor", "2.3.4").withConfigurations(Some("compile")) cross CrossVersion.binary
|
||||||
|
def scala2102 =
|
||||||
|
ModuleID("org.scala-lang", "scala-library", "2.10.2").withConfigurations(Some("compile"))
|
||||||
|
def scala2103 =
|
||||||
|
ModuleID("org.scala-lang", "scala-library", "2.10.3").withConfigurations(Some("compile"))
|
||||||
|
def scala2104 =
|
||||||
|
ModuleID("org.scala-lang", "scala-library", "2.10.4").withConfigurations(Some("compile"))
|
||||||
def commonsIo13 = ModuleID("commons-io", "commons-io", "1.3").withConfigurations(Some("compile"))
|
def commonsIo13 = ModuleID("commons-io", "commons-io", "1.3").withConfigurations(Some("compile"))
|
||||||
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 = ModuleID("ca.gobits.bnf", "bnfparser", "1.0").withConfigurations(Some("compile")) // uses commons-io 2.4
|
def bnfparser10 =
|
||||||
def unfilteredUploads080 = ModuleID("net.databinder", "unfiltered-uploads", "0.8.0").withConfigurations(Some("compile")) cross CrossVersion.binary // uses commons-io 1.4
|
ModuleID("ca.gobits.bnf", "bnfparser", "1.0").withConfigurations(Some("compile")) // uses commons-io 2.4
|
||||||
def bananaSesame04 = ModuleID("org.w3", "banana-sesame", "0.4").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.1.4
|
def unfilteredUploads080 =
|
||||||
def akkaRemote234 = ModuleID("com.typesafe.akka", "akka-remote", "2.3.4").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.3.4
|
ModuleID("net.databinder", "unfiltered-uploads", "0.8.0").withConfigurations(Some("compile")) cross CrossVersion.binary // uses commons-io 1.4
|
||||||
|
def bananaSesame04 =
|
||||||
|
ModuleID("org.w3", "banana-sesame", "0.4").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.1.4
|
||||||
|
def akkaRemote234 =
|
||||||
|
ModuleID("com.typesafe.akka", "akka-remote", "2.3.4").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.3.4
|
||||||
|
|
||||||
def defaultOptions = EvictionWarningOptions.default
|
def defaultOptions = EvictionWarningOptions.default
|
||||||
|
|
||||||
|
|
@ -181,7 +191,10 @@ class EvictionWarningSpec extends BaseIvySpecification {
|
||||||
def javaLibTransitiveWarn3() = {
|
def javaLibTransitiveWarn3() = {
|
||||||
val m = module(defaultModuleId, javaLibTransitiveDeps, Some("2.10.3"))
|
val m = module(defaultModuleId, javaLibTransitiveDeps, Some("2.10.3"))
|
||||||
val report = ivyUpdate(m)
|
val report = ivyUpdate(m)
|
||||||
EvictionWarning(m, defaultOptions.withWarnTransitiveEvictions(true).withShowCallers(true), report, log).lines shouldBe
|
EvictionWarning(m,
|
||||||
|
defaultOptions.withWarnTransitiveEvictions(true).withShowCallers(true),
|
||||||
|
report,
|
||||||
|
log).lines shouldBe
|
||||||
List(
|
List(
|
||||||
"There may be incompatibilities among your library dependencies.",
|
"There may be incompatibilities among your library dependencies.",
|
||||||
"Here are some of the libraries that were evicted:",
|
"Here are some of the libraries that were evicted:",
|
||||||
|
|
@ -240,7 +253,10 @@ class EvictionWarningSpec extends BaseIvySpecification {
|
||||||
def scalaLibTransitiveWarn3() = {
|
def scalaLibTransitiveWarn3() = {
|
||||||
val m = module(defaultModuleId, scalaLibTransitiveDeps, Some("2.10.4"))
|
val m = module(defaultModuleId, scalaLibTransitiveDeps, Some("2.10.4"))
|
||||||
val report = ivyUpdate(m)
|
val report = ivyUpdate(m)
|
||||||
EvictionWarning(m, defaultOptions.withWarnTransitiveEvictions(true).withShowCallers(true), report, log).lines shouldBe
|
EvictionWarning(m,
|
||||||
|
defaultOptions.withWarnTransitiveEvictions(true).withShowCallers(true),
|
||||||
|
report,
|
||||||
|
log).lines shouldBe
|
||||||
List(
|
List(
|
||||||
"There may be incompatibilities among your library dependencies.",
|
"There may be incompatibilities among your library dependencies.",
|
||||||
"Here are some of the libraries that were evicted:",
|
"Here are some of the libraries that were evicted:",
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,10 @@ class InconsistentDuplicateSpec extends UnitSpec {
|
||||||
IvySbt.inconsistentDuplicateWarning(Seq(akkaActor230Test, akkaActor230)) shouldBe Nil
|
IvySbt.inconsistentDuplicateWarning(Seq(akkaActor230Test, akkaActor230)) shouldBe Nil
|
||||||
}
|
}
|
||||||
|
|
||||||
def akkaActor214 = ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(Some("compile")) cross CrossVersion.binary
|
def akkaActor214 =
|
||||||
def akkaActor230 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("compile")) cross CrossVersion.binary
|
ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(Some("compile")) cross CrossVersion.binary
|
||||||
def akkaActor230Test = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("test")) cross CrossVersion.binary
|
def akkaActor230 =
|
||||||
|
ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("compile")) cross CrossVersion.binary
|
||||||
|
def akkaActor230Test =
|
||||||
|
ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("test")) cross CrossVersion.binary
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,4 +75,3 @@ class MakePomSpec extends UnitSpec {
|
||||||
()
|
()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@ class MergeDescriptorSpec extends BaseIvySpecification {
|
||||||
cleanIvyCache()
|
cleanIvyCache()
|
||||||
val m = module(
|
val m = module(
|
||||||
ModuleID("com.example", "foo", "0.1.0").withConfigurations(Some("compile")),
|
ModuleID("com.example", "foo", "0.1.0").withConfigurations(Some("compile")),
|
||||||
Vector(guavaTest, guavaTestTests), None, UpdateOptions()
|
Vector(guavaTest, guavaTestTests),
|
||||||
|
None,
|
||||||
|
UpdateOptions()
|
||||||
)
|
)
|
||||||
m.withModule(log) {
|
m.withModule(log) {
|
||||||
case (ivy, md, _) =>
|
case (ivy, md, _) =>
|
||||||
|
|
@ -27,8 +29,12 @@ class MergeDescriptorSpec extends BaseIvySpecification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def guavaTest = ModuleID("com.google.guava", "guava-tests", "18.0").withConfigurations(Option("compile"))
|
def guavaTest =
|
||||||
def guavaTestTests = ModuleID("com.google.guava", "guava-tests", "18.0").withConfigurations(Option("test")).classifier("tests")
|
ModuleID("com.google.guava", "guava-tests", "18.0").withConfigurations(Option("compile"))
|
||||||
|
def guavaTestTests =
|
||||||
|
ModuleID("com.google.guava", "guava-tests", "18.0")
|
||||||
|
.withConfigurations(Option("test"))
|
||||||
|
.classifier("tests")
|
||||||
def defaultOptions = EvictionWarningOptions.default
|
def defaultOptions = EvictionWarningOptions.default
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,14 @@ object ResolverTest extends UnitSpec {
|
||||||
"Resolver url" should "propagate pattern descriptorOptional and skipConsistencyCheck." in {
|
"Resolver url" should "propagate pattern descriptorOptional and skipConsistencyCheck." in {
|
||||||
val pats = Vector("[orgPath]")
|
val pats = Vector("[orgPath]")
|
||||||
val patsExpected = Vector("http://foo.com/test/[orgPath]")
|
val patsExpected = Vector("http://foo.com/test/[orgPath]")
|
||||||
val patterns = Resolver.url("test", new URL("http://foo.com/test"))(Patterns(pats, pats, isMavenCompatible = false, descriptorOptional = true, skipConsistencyCheck = true)).patterns
|
val patterns = Resolver
|
||||||
|
.url("test", new URL("http://foo.com/test"))(
|
||||||
|
Patterns(pats,
|
||||||
|
pats,
|
||||||
|
isMavenCompatible = false,
|
||||||
|
descriptorOptional = true,
|
||||||
|
skipConsistencyCheck = true))
|
||||||
|
.patterns
|
||||||
|
|
||||||
patterns.ivyPatterns shouldBe patsExpected
|
patterns.ivyPatterns shouldBe patsExpected
|
||||||
patterns.artifactPatterns shouldBe patsExpected
|
patterns.artifactPatterns shouldBe patsExpected
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ class ScalaOverrideTest extends UnitSpec {
|
||||||
val OtherOrgID = "other.org"
|
val OtherOrgID = "other.org"
|
||||||
|
|
||||||
def check(org0: String, version0: String)(org1: String, name1: String, version1: String) = {
|
def check(org0: String, version0: String)(org1: String, name1: String, version1: String) = {
|
||||||
val scalaConfigs = Configurations.default.toVector filter { Configurations.underScalaVersion } map { _.name }
|
val scalaConfigs = Configurations.default.toVector filter { Configurations.underScalaVersion } map {
|
||||||
|
_.name
|
||||||
|
}
|
||||||
val osm = new OverrideScalaMediator(org0, version0, scalaConfigs)
|
val osm = new OverrideScalaMediator(org0, version0, scalaConfigs)
|
||||||
|
|
||||||
val mrid = ModuleRevisionId.newInstance(org1, name1, version1)
|
val mrid = ModuleRevisionId.newInstance(org1, name1, version1)
|
||||||
|
|
@ -24,21 +26,51 @@ class ScalaOverrideTest extends UnitSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
"""OverrideScalaMediator
|
"""OverrideScalaMediator
|
||||||
""" should "Override compiler version" in check(Organization, "2.11.8")(Organization, CompilerID, "2.11.9")
|
""" should "Override compiler version" in check(Organization, "2.11.8")(Organization,
|
||||||
it should "Override library version" in check(Organization, "2.11.8")(Organization, LibraryID, "2.11.8")
|
CompilerID,
|
||||||
it should "Override reflect version" in check(Organization, "2.11.8")(Organization, ReflectID, "2.11.7")
|
"2.11.9")
|
||||||
it should "Override actors version" in check(Organization, "2.11.8")(Organization, ActorsID, "2.11.6")
|
it should "Override library version" in check(Organization, "2.11.8")(Organization,
|
||||||
it should "Override scalap version" in check(Organization, "2.11.8")(Organization, ScalapID, "2.11.5")
|
LibraryID,
|
||||||
|
"2.11.8")
|
||||||
|
it should "Override reflect version" in check(Organization, "2.11.8")(Organization,
|
||||||
|
ReflectID,
|
||||||
|
"2.11.7")
|
||||||
|
it should "Override actors version" in check(Organization, "2.11.8")(Organization,
|
||||||
|
ActorsID,
|
||||||
|
"2.11.6")
|
||||||
|
it should "Override scalap version" in check(Organization, "2.11.8")(Organization,
|
||||||
|
ScalapID,
|
||||||
|
"2.11.5")
|
||||||
|
|
||||||
it should "Override default compiler organization" in check(OtherOrgID, "2.11.8")(Organization, CompilerID, "2.11.9")
|
it should "Override default compiler organization" in check(OtherOrgID, "2.11.8")(Organization,
|
||||||
it should "Override default library organization" in check(OtherOrgID, "2.11.8")(Organization, LibraryID, "2.11.8")
|
CompilerID,
|
||||||
it should "Override default reflect organization" in check(OtherOrgID, "2.11.8")(Organization, ReflectID, "2.11.7")
|
"2.11.9")
|
||||||
it should "Override default actors organization" in check(OtherOrgID, "2.11.8")(Organization, ActorsID, "2.11.6")
|
it should "Override default library organization" in check(OtherOrgID, "2.11.8")(Organization,
|
||||||
it should "Override default scalap organization" in check(OtherOrgID, "2.11.8")(Organization, ScalapID, "2.11.5")
|
LibraryID,
|
||||||
|
"2.11.8")
|
||||||
|
it should "Override default reflect organization" in check(OtherOrgID, "2.11.8")(Organization,
|
||||||
|
ReflectID,
|
||||||
|
"2.11.7")
|
||||||
|
it should "Override default actors organization" in check(OtherOrgID, "2.11.8")(Organization,
|
||||||
|
ActorsID,
|
||||||
|
"2.11.6")
|
||||||
|
it should "Override default scalap organization" in check(OtherOrgID, "2.11.8")(Organization,
|
||||||
|
ScalapID,
|
||||||
|
"2.11.5")
|
||||||
|
|
||||||
it should "Override custom compiler organization" in check(Organization, "2.11.8")(OtherOrgID, CompilerID, "2.11.9")
|
it should "Override custom compiler organization" in check(Organization, "2.11.8")(OtherOrgID,
|
||||||
it should "Override custom library organization" in check(Organization, "2.11.8")(OtherOrgID, LibraryID, "2.11.8")
|
CompilerID,
|
||||||
it should "Override custom reflect organization" in check(Organization, "2.11.8")(OtherOrgID, ReflectID, "2.11.7")
|
"2.11.9")
|
||||||
it should "Override custom actors organization" in check(Organization, "2.11.8")(OtherOrgID, ActorsID, "2.11.6")
|
it should "Override custom library organization" in check(Organization, "2.11.8")(OtherOrgID,
|
||||||
it should "Override custom scalap organization" in check(Organization, "2.11.8")(OtherOrgID, ScalapID, "2.11.5")
|
LibraryID,
|
||||||
|
"2.11.8")
|
||||||
|
it should "Override custom reflect organization" in check(Organization, "2.11.8")(OtherOrgID,
|
||||||
|
ReflectID,
|
||||||
|
"2.11.7")
|
||||||
|
it should "Override custom actors organization" in check(Organization, "2.11.8")(OtherOrgID,
|
||||||
|
ActorsID,
|
||||||
|
"2.11.6")
|
||||||
|
it should "Override custom scalap organization" in check(Organization, "2.11.8")(OtherOrgID,
|
||||||
|
ScalapID,
|
||||||
|
"2.11.5")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,45 +38,72 @@ class VersionNumberSpec extends UnitSpec {
|
||||||
it should "be SecSeg compat with 0.12.1" in beSecSegCompatWith("0.12.0", "0.12.1")
|
it should "be SecSeg compat with 0.12.1" in beSecSegCompatWith("0.12.0", "0.12.1")
|
||||||
it should "be SecSeg compat with 0.12.1-M1" in beSecSegCompatWith("0.12.0", "0.12.1-M1")
|
it should "be SecSeg compat with 0.12.1-M1" in beSecSegCompatWith("0.12.0", "0.12.1-M1")
|
||||||
|
|
||||||
"0.1.0-SNAPSHOT" should "be parsed" in beParsedAs("0.1.0-SNAPSHOT", Seq(0, 1, 0), Seq("SNAPSHOT"), Seq())
|
"0.1.0-SNAPSHOT" should "be parsed" in beParsedAs("0.1.0-SNAPSHOT",
|
||||||
it should "cascade" in generateCorrectCascadingNumbers("0.1.0-SNAPSHOT", Seq("0.1.0-SNAPSHOT", "0.1.0", "0.1"))
|
Seq(0, 1, 0),
|
||||||
it should "be SemVer compat with 0.1.0-SNAPSHOT" in beSemVerCompatWith("0.1.0-SNAPSHOT", "0.1.0-SNAPSHOT")
|
Seq("SNAPSHOT"),
|
||||||
|
Seq())
|
||||||
|
it should "cascade" in generateCorrectCascadingNumbers("0.1.0-SNAPSHOT",
|
||||||
|
Seq("0.1.0-SNAPSHOT", "0.1.0", "0.1"))
|
||||||
|
it should "be SemVer compat with 0.1.0-SNAPSHOT" in beSemVerCompatWith("0.1.0-SNAPSHOT",
|
||||||
|
"0.1.0-SNAPSHOT")
|
||||||
it should "not be SemVer compat with 0.1.0" in notBeSemVerCompatWith("0.1.0-SNAPSHOT", "0.1.0")
|
it should "not be SemVer compat with 0.1.0" in notBeSemVerCompatWith("0.1.0-SNAPSHOT", "0.1.0")
|
||||||
it should "be SemVer compat with 0.1.0-SNAPSHOT+001" in beSemVerCompatWith("0.1.0-SNAPSHOT", "0.1.0-SNAPSHOT+001")
|
it should "be SemVer compat with 0.1.0-SNAPSHOT+001" in beSemVerCompatWith("0.1.0-SNAPSHOT",
|
||||||
it should "be SecSeg compat with 0.1.0-SNAPSHOT" in beSecSegCompatWith("0.1.0-SNAPSHOT", "0.1.0-SNAPSHOT")
|
"0.1.0-SNAPSHOT+001")
|
||||||
|
it should "be SecSeg compat with 0.1.0-SNAPSHOT" in beSecSegCompatWith("0.1.0-SNAPSHOT",
|
||||||
|
"0.1.0-SNAPSHOT")
|
||||||
it should "be not SecSeg compat with 0.1.0" in notBeSecSegCompatWith("0.1.0-SNAPSHOT", "0.1.0")
|
it should "be not SecSeg compat with 0.1.0" in notBeSecSegCompatWith("0.1.0-SNAPSHOT", "0.1.0")
|
||||||
it should "be SecSeg compat with 0.1.0-SNAPSHOT+001" in beSecSegCompatWith("0.1.0-SNAPSHOT", "0.1.0-SNAPSHOT+001")
|
it should "be SecSeg compat with 0.1.0-SNAPSHOT+001" in beSecSegCompatWith("0.1.0-SNAPSHOT",
|
||||||
|
"0.1.0-SNAPSHOT+001")
|
||||||
|
|
||||||
"0.1.0-M1" should "be parsed" in beParsedAs("0.1.0-M1", Seq(0, 1, 0), Seq("M1"), Seq())
|
"0.1.0-M1" should "be parsed" in beParsedAs("0.1.0-M1", Seq(0, 1, 0), Seq("M1"), Seq())
|
||||||
it should "cascade" in generateCorrectCascadingNumbers("0.1.0-M1", Seq("0.1.0-M1", "0.1.0", "0.1"))
|
it should "cascade" in generateCorrectCascadingNumbers("0.1.0-M1",
|
||||||
|
Seq("0.1.0-M1", "0.1.0", "0.1"))
|
||||||
|
|
||||||
"0.1.0-RC1" should "be parsed" in beParsedAs("0.1.0-RC1", Seq(0, 1, 0), Seq("RC1"), Seq())
|
"0.1.0-RC1" should "be parsed" in beParsedAs("0.1.0-RC1", Seq(0, 1, 0), Seq("RC1"), Seq())
|
||||||
it should "cascade" in generateCorrectCascadingNumbers("0.1.0-RC1", Seq("0.1.0-RC1", "0.1.0", "0.1"))
|
it should "cascade" in generateCorrectCascadingNumbers("0.1.0-RC1",
|
||||||
|
Seq("0.1.0-RC1", "0.1.0", "0.1"))
|
||||||
|
|
||||||
"0.1.0-MSERVER-1" should "be parsed" in beParsedAs("0.1.0-MSERVER-1", Seq(0, 1, 0), Seq("MSERVER", "1"), Seq())
|
"0.1.0-MSERVER-1" should "be parsed" in beParsedAs("0.1.0-MSERVER-1",
|
||||||
it should "cascade" in generateCorrectCascadingNumbers("0.1.0-MSERVER-1", Seq("0.1.0-MSERVER-1", "0.1.0", "0.1"))
|
Seq(0, 1, 0),
|
||||||
|
Seq("MSERVER", "1"),
|
||||||
|
Seq())
|
||||||
|
it should "cascade" in generateCorrectCascadingNumbers("0.1.0-MSERVER-1",
|
||||||
|
Seq("0.1.0-MSERVER-1", "0.1.0", "0.1"))
|
||||||
|
|
||||||
"2.10.4-20140115-000117-b3a-sources" should "be parsed" in {
|
"2.10.4-20140115-000117-b3a-sources" should "be parsed" in {
|
||||||
beParsedAs("2.10.4-20140115-000117-b3a-sources", Seq(2, 10, 4), Seq("20140115", "000117", "b3a", "sources"), Seq())
|
beParsedAs("2.10.4-20140115-000117-b3a-sources",
|
||||||
|
Seq(2, 10, 4),
|
||||||
|
Seq("20140115", "000117", "b3a", "sources"),
|
||||||
|
Seq())
|
||||||
}
|
}
|
||||||
it should "cascade" in generateCorrectCascadingNumbers("2.10.4-20140115-000117-b3a-sources", Seq("2.10.4-20140115-000117-b3a-sources", "2.10.4", "2.10"))
|
it should "cascade" in generateCorrectCascadingNumbers(
|
||||||
it should "be SemVer compat with 2.0.0" in beSemVerCompatWith("2.10.4-20140115-000117-b3a-sources", "2.0.0")
|
"2.10.4-20140115-000117-b3a-sources",
|
||||||
it should "be not SecSeg compat with 2.0.0" in notBeSecSegCompatWith("2.10.4-20140115-000117-b3a-sources", "2.0.0")
|
Seq("2.10.4-20140115-000117-b3a-sources", "2.10.4", "2.10"))
|
||||||
|
it should "be SemVer compat with 2.0.0" in beSemVerCompatWith(
|
||||||
|
"2.10.4-20140115-000117-b3a-sources",
|
||||||
|
"2.0.0")
|
||||||
|
it should "be not SecSeg compat with 2.0.0" in notBeSecSegCompatWith(
|
||||||
|
"2.10.4-20140115-000117-b3a-sources",
|
||||||
|
"2.0.0")
|
||||||
|
|
||||||
"20140115000117-b3a-sources" should "be parsed" in {
|
"20140115000117-b3a-sources" should "be parsed" in {
|
||||||
beParsedAs("20140115000117-b3a-sources", Seq(20140115000117L), Seq("b3a", "sources"), Seq())
|
beParsedAs("20140115000117-b3a-sources", Seq(20140115000117L), Seq("b3a", "sources"), Seq())
|
||||||
}
|
}
|
||||||
it should "cascade" in generateCorrectCascadingNumbers("20140115000117-b3a-sources", Seq("20140115000117-b3a-sources"))
|
it should "cascade" in generateCorrectCascadingNumbers("20140115000117-b3a-sources",
|
||||||
|
Seq("20140115000117-b3a-sources"))
|
||||||
|
|
||||||
"1.0.0-alpha+001+002" should "be parsed" in {
|
"1.0.0-alpha+001+002" should "be parsed" in {
|
||||||
beParsedAs("1.0.0-alpha+001+002", Seq(1, 0, 0), Seq("alpha"), Seq("+001", "+002"))
|
beParsedAs("1.0.0-alpha+001+002", Seq(1, 0, 0), Seq("alpha"), Seq("+001", "+002"))
|
||||||
}
|
}
|
||||||
it should "cascade" in generateCorrectCascadingNumbers("1.0.0-alpha+001+002", Seq("1.0.0-alpha+001+002", "1.0.0", "1.0"))
|
it should "cascade" in generateCorrectCascadingNumbers(
|
||||||
|
"1.0.0-alpha+001+002",
|
||||||
|
Seq("1.0.0-alpha+001+002", "1.0.0", "1.0"))
|
||||||
|
|
||||||
"non.space.!?string" should "be parsed" in {
|
"non.space.!?string" should "be parsed" in {
|
||||||
beParsedAs("non.space.!?string", Seq(), Seq(), Seq("non.space.!?string"))
|
beParsedAs("non.space.!?string", Seq(), Seq(), Seq("non.space.!?string"))
|
||||||
}
|
}
|
||||||
it should "cascade" in generateCorrectCascadingNumbers("non.space.!?string", Seq("non.space.!?string"))
|
it should "cascade" in generateCorrectCascadingNumbers("non.space.!?string",
|
||||||
|
Seq("non.space.!?string"))
|
||||||
|
|
||||||
"space !?string" should "be parsed as an error" in beParsedAsError("space !?string")
|
"space !?string" should "be parsed as an error" in beParsedAsError("space !?string")
|
||||||
"blank string" should "be parsed as an error" in beParsedAsError("")
|
"blank string" should "be parsed as an error" in beParsedAsError("")
|
||||||
|
|
@ -89,8 +116,11 @@ class VersionNumberSpec extends UnitSpec {
|
||||||
case VersionNumber(ns1, ts1, es1) =>
|
case VersionNumber(ns1, ts1, es1) =>
|
||||||
sys.error(s"$ns1, $ts1, $es1")
|
sys.error(s"$ns1, $ts1, $es1")
|
||||||
}
|
}
|
||||||
def breakDownTo(s: String, major: Option[Long], minor: Option[Long] = None,
|
def breakDownTo(s: String,
|
||||||
patch: Option[Long] = None, buildNumber: Option[Long] = None) =
|
major: Option[Long],
|
||||||
|
minor: Option[Long] = None,
|
||||||
|
patch: Option[Long] = None,
|
||||||
|
buildNumber: Option[Long] = None) =
|
||||||
s match {
|
s match {
|
||||||
case VersionNumber(ns, ts, es) =>
|
case VersionNumber(ns, ts, es) =>
|
||||||
val v = VersionNumber(ns, ts, es)
|
val v = VersionNumber(ns, ts, es)
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,13 @@ import sbt.librarymanagement.{ ModuleID, RawRepository, Resolver, UpdateReport }
|
||||||
class FakeResolverSpecification extends BaseIvySpecification {
|
class FakeResolverSpecification extends BaseIvySpecification {
|
||||||
import FakeResolver._
|
import FakeResolver._
|
||||||
|
|
||||||
val myModule = ModuleID("org.example", "my-module", "0.0.1-SNAPSHOT").withConfigurations(Some("compile"))
|
val myModule =
|
||||||
|
ModuleID("org.example", "my-module", "0.0.1-SNAPSHOT").withConfigurations(Some("compile"))
|
||||||
val example = ModuleID("com.example", "example", "1.0.0").withConfigurations(Some("compile"))
|
val example = ModuleID("com.example", "example", "1.0.0").withConfigurations(Some("compile"))
|
||||||
val anotherExample = ModuleID("com.example", "another-example", "1.0.0").withConfigurations(Some("compile"))
|
val anotherExample =
|
||||||
val nonExisting = ModuleID("com.example", "does-not-exist", "1.2.3").withConfigurations(Some("compile"))
|
ModuleID("com.example", "another-example", "1.0.0").withConfigurations(Some("compile"))
|
||||||
|
val nonExisting =
|
||||||
|
ModuleID("com.example", "does-not-exist", "1.2.3").withConfigurations(Some("compile"))
|
||||||
|
|
||||||
"The FakeResolver" should "find modules with only one artifact" in {
|
"The FakeResolver" should "find modules with only one artifact" in {
|
||||||
val m = getModule(myModule)
|
val m = getModule(myModule)
|
||||||
|
|
@ -53,12 +56,10 @@ class FakeResolverSpecification extends BaseIvySpecification {
|
||||||
("org.example", "my-module", "0.0.1-SNAPSHOT") -> List(
|
("org.example", "my-module", "0.0.1-SNAPSHOT") -> List(
|
||||||
FakeArtifact("artifact1", "jar", "jar", artifact1)
|
FakeArtifact("artifact1", "jar", "jar", artifact1)
|
||||||
),
|
),
|
||||||
|
|
||||||
("com.example", "example", "1.0.0") -> List(
|
("com.example", "example", "1.0.0") -> List(
|
||||||
FakeArtifact("artifact1", "jar", "jar", artifact1),
|
FakeArtifact("artifact1", "jar", "jar", artifact1),
|
||||||
FakeArtifact("artifact2", "txt", "txt", artifact2)
|
FakeArtifact("artifact2", "txt", "txt", artifact2)
|
||||||
),
|
),
|
||||||
|
|
||||||
("com.example", "another-example", "1.0.0") -> List(
|
("com.example", "another-example", "1.0.0") -> List(
|
||||||
FakeArtifact("artifact1", "jar", "jar", artifact1),
|
FakeArtifact("artifact1", "jar", "jar", artifact1),
|
||||||
FakeArtifact("non-existing", "txt", "txt", new File("non-existing-file"))
|
FakeArtifact("non-existing", "txt", "txt", new File("non-existing-file"))
|
||||||
|
|
@ -67,7 +68,8 @@ class FakeResolverSpecification extends BaseIvySpecification {
|
||||||
|
|
||||||
private def fakeResolver = new FakeResolver("FakeResolver", new File("tmp"), modules)
|
private def fakeResolver = new FakeResolver("FakeResolver", new File("tmp"), modules)
|
||||||
override def resolvers: Vector[Resolver] = Vector(new RawRepository(fakeResolver))
|
override def resolvers: Vector[Resolver] = Vector(new RawRepository(fakeResolver))
|
||||||
private def getModule(myModule: ModuleID): IvySbt#Module = module(defaultModuleId, Vector(myModule), None)
|
private def getModule(myModule: ModuleID): IvySbt#Module =
|
||||||
|
module(defaultModuleId, Vector(myModule), None)
|
||||||
private def getAllFiles(report: UpdateReport) =
|
private def getAllFiles(report: UpdateReport) =
|
||||||
for {
|
for {
|
||||||
conf <- report.configurations
|
conf <- report.configurations
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ class IvyRepoSpec extends BaseIvySpecification with DependencyBuilders {
|
||||||
|
|
||||||
module(
|
module(
|
||||||
ourModuleID,
|
ourModuleID,
|
||||||
Vector(dep), None //, UpdateOptions().withCachedResolution(true)
|
Vector(dep),
|
||||||
|
None //, UpdateOptions().withCachedResolution(true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,12 +60,26 @@ class IvyRepoSpec extends BaseIvySpecification with DependencyBuilders {
|
||||||
val clMod = {
|
val clMod = {
|
||||||
val externalModules = Vector(dep)
|
val externalModules = Vector(dep)
|
||||||
// Note: need to extract ourModuleID so we can plug it in here, can't fish it back out of the IvySbt#Module (`m`)
|
// Note: need to extract ourModuleID so we can plug it in here, can't fish it back out of the IvySbt#Module (`m`)
|
||||||
GetClassifiersModule(ourModuleID, externalModules, Vector(Configurations.Compile), attemptedClassifiers)
|
GetClassifiersModule(ourModuleID,
|
||||||
|
externalModules,
|
||||||
|
Vector(Configurations.Compile),
|
||||||
|
attemptedClassifiers)
|
||||||
}
|
}
|
||||||
|
|
||||||
val gcm = GetClassifiersConfiguration(clMod, Map.empty, c.withArtifactFilter(c.artifactFilter.invert), ivyScala, srcTypes, docTypes)
|
val gcm = GetClassifiersConfiguration(clMod,
|
||||||
|
Map.empty,
|
||||||
|
c.withArtifactFilter(c.artifactFilter.invert),
|
||||||
|
ivyScala,
|
||||||
|
srcTypes,
|
||||||
|
docTypes)
|
||||||
|
|
||||||
val report2 = IvyActions.updateClassifiers(m.owner, gcm, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, Vector(), log)
|
val report2 = IvyActions.updateClassifiers(m.owner,
|
||||||
|
gcm,
|
||||||
|
UnresolvedWarningConfiguration(),
|
||||||
|
LogicalClock.unknown,
|
||||||
|
None,
|
||||||
|
Vector(),
|
||||||
|
log)
|
||||||
|
|
||||||
import Inside._
|
import Inside._
|
||||||
inside(report2.configuration("compile").map(_.modules)) {
|
inside(report2.configuration("compile").map(_.modules)) {
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,16 @@ class RepositoriesParserSpecification extends UnitSpec {
|
||||||
| ivyRepo: https://repo1.maven.org, [orgPath], bootOnly""".stripMargin
|
| ivyRepo: https://repo1.maven.org, [orgPath], bootOnly""".stripMargin
|
||||||
val repos = RepositoriesParser(file)
|
val repos = RepositoriesParser(file)
|
||||||
val expected =
|
val expected =
|
||||||
IvyRepository("ivyRepo", new URL("https://repo1.maven.org"), "[orgPath]", "[orgPath]",
|
IvyRepository(
|
||||||
|
"ivyRepo",
|
||||||
|
new URL("https://repo1.maven.org"),
|
||||||
|
"[orgPath]",
|
||||||
|
"[orgPath]",
|
||||||
mavenCompatible = false,
|
mavenCompatible = false,
|
||||||
skipConsistencyCheck = false,
|
skipConsistencyCheck = false,
|
||||||
descriptorOptional = false,
|
descriptorOptional = false,
|
||||||
bootOnly = true)
|
bootOnly = true
|
||||||
|
)
|
||||||
repos.size shouldBe 1
|
repos.size shouldBe 1
|
||||||
repos(0) shouldBe expected
|
repos(0) shouldBe expected
|
||||||
}
|
}
|
||||||
|
|
@ -68,11 +73,16 @@ class RepositoriesParserSpecification extends UnitSpec {
|
||||||
| ivyRepo: https://repo1.maven.org, [orgPath], mavenCompatible""".stripMargin
|
| ivyRepo: https://repo1.maven.org, [orgPath], mavenCompatible""".stripMargin
|
||||||
val repos = RepositoriesParser(file)
|
val repos = RepositoriesParser(file)
|
||||||
val expected =
|
val expected =
|
||||||
IvyRepository("ivyRepo", new URL("https://repo1.maven.org"), "[orgPath]", "[orgPath]",
|
IvyRepository(
|
||||||
|
"ivyRepo",
|
||||||
|
new URL("https://repo1.maven.org"),
|
||||||
|
"[orgPath]",
|
||||||
|
"[orgPath]",
|
||||||
mavenCompatible = true,
|
mavenCompatible = true,
|
||||||
skipConsistencyCheck = false,
|
skipConsistencyCheck = false,
|
||||||
descriptorOptional = false,
|
descriptorOptional = false,
|
||||||
bootOnly = false)
|
bootOnly = false
|
||||||
|
)
|
||||||
repos.size shouldBe 1
|
repos.size shouldBe 1
|
||||||
repos(0) shouldBe expected
|
repos(0) shouldBe expected
|
||||||
}
|
}
|
||||||
|
|
@ -82,11 +92,16 @@ class RepositoriesParserSpecification extends UnitSpec {
|
||||||
| ivyRepo: https://repo1.maven.org, [orgPath], skipConsistencyCheck""".stripMargin
|
| ivyRepo: https://repo1.maven.org, [orgPath], skipConsistencyCheck""".stripMargin
|
||||||
val repos = RepositoriesParser(file)
|
val repos = RepositoriesParser(file)
|
||||||
val expected =
|
val expected =
|
||||||
IvyRepository("ivyRepo", new URL("https://repo1.maven.org"), "[orgPath]", "[orgPath]",
|
IvyRepository(
|
||||||
|
"ivyRepo",
|
||||||
|
new URL("https://repo1.maven.org"),
|
||||||
|
"[orgPath]",
|
||||||
|
"[orgPath]",
|
||||||
mavenCompatible = false,
|
mavenCompatible = false,
|
||||||
skipConsistencyCheck = true,
|
skipConsistencyCheck = true,
|
||||||
descriptorOptional = false,
|
descriptorOptional = false,
|
||||||
bootOnly = false)
|
bootOnly = false
|
||||||
|
)
|
||||||
repos.size shouldBe 1
|
repos.size shouldBe 1
|
||||||
repos(0) shouldBe expected
|
repos(0) shouldBe expected
|
||||||
}
|
}
|
||||||
|
|
@ -96,41 +111,58 @@ class RepositoriesParserSpecification extends UnitSpec {
|
||||||
| ivyRepo: https://repo1.maven.org, [orgPath], descriptorOptional""".stripMargin
|
| ivyRepo: https://repo1.maven.org, [orgPath], descriptorOptional""".stripMargin
|
||||||
val repos = RepositoriesParser(file)
|
val repos = RepositoriesParser(file)
|
||||||
val expected =
|
val expected =
|
||||||
IvyRepository("ivyRepo", new URL("https://repo1.maven.org"), "[orgPath]", "[orgPath]",
|
IvyRepository(
|
||||||
|
"ivyRepo",
|
||||||
|
new URL("https://repo1.maven.org"),
|
||||||
|
"[orgPath]",
|
||||||
|
"[orgPath]",
|
||||||
mavenCompatible = false,
|
mavenCompatible = false,
|
||||||
skipConsistencyCheck = false,
|
skipConsistencyCheck = false,
|
||||||
descriptorOptional = true,
|
descriptorOptional = true,
|
||||||
bootOnly = false)
|
bootOnly = false
|
||||||
|
)
|
||||||
repos.size shouldBe 1
|
repos.size shouldBe 1
|
||||||
repos(0) shouldBe expected
|
repos(0) shouldBe expected
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "parse complex ivy repository definition" in {
|
it should "parse complex ivy repository definition" in {
|
||||||
val file = """[repositories]
|
val file =
|
||||||
|
"""[repositories]
|
||||||
| ivyRepo: https://repo1.maven.org, [orgPath], [artPath], descriptorOptional, skipConsistencyCheck""".stripMargin
|
| ivyRepo: https://repo1.maven.org, [orgPath], [artPath], descriptorOptional, skipConsistencyCheck""".stripMargin
|
||||||
val repos = RepositoriesParser(file)
|
val repos = RepositoriesParser(file)
|
||||||
val expected =
|
val expected =
|
||||||
IvyRepository("ivyRepo", new URL("https://repo1.maven.org"), "[orgPath]", "[artPath]",
|
IvyRepository(
|
||||||
|
"ivyRepo",
|
||||||
|
new URL("https://repo1.maven.org"),
|
||||||
|
"[orgPath]",
|
||||||
|
"[artPath]",
|
||||||
mavenCompatible = false,
|
mavenCompatible = false,
|
||||||
skipConsistencyCheck = true,
|
skipConsistencyCheck = true,
|
||||||
descriptorOptional = true,
|
descriptorOptional = true,
|
||||||
bootOnly = false)
|
bootOnly = false
|
||||||
|
)
|
||||||
repos.size shouldBe 1
|
repos.size shouldBe 1
|
||||||
repos(0) shouldBe expected
|
repos(0) shouldBe expected
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "parse multiple repositories defined together" in {
|
it should "parse multiple repositories defined together" in {
|
||||||
val file = """[repositories]
|
val file =
|
||||||
|
"""[repositories]
|
||||||
| local
|
| local
|
||||||
| ivyRepo: https://repo1.maven.org, [orgPath], [artPath], descriptorOptional, skipConsistencyCheck
|
| ivyRepo: https://repo1.maven.org, [orgPath], [artPath], descriptorOptional, skipConsistencyCheck
|
||||||
| mavenRepo: https://repo1.maven.org""".stripMargin
|
| mavenRepo: https://repo1.maven.org""".stripMargin
|
||||||
val expected0 = PredefinedRepository(xsbti.Predefined.Local)
|
val expected0 = PredefinedRepository(xsbti.Predefined.Local)
|
||||||
val expected1 =
|
val expected1 =
|
||||||
IvyRepository("ivyRepo", new URL("https://repo1.maven.org"), "[orgPath]", "[artPath]",
|
IvyRepository(
|
||||||
|
"ivyRepo",
|
||||||
|
new URL("https://repo1.maven.org"),
|
||||||
|
"[orgPath]",
|
||||||
|
"[artPath]",
|
||||||
mavenCompatible = false,
|
mavenCompatible = false,
|
||||||
skipConsistencyCheck = true,
|
skipConsistencyCheck = true,
|
||||||
descriptorOptional = true,
|
descriptorOptional = true,
|
||||||
bootOnly = false)
|
bootOnly = false
|
||||||
|
)
|
||||||
val expected2 = MavenRepository("mavenRepo", new URL("https://repo1.maven.org"))
|
val expected2 = MavenRepository("mavenRepo", new URL("https://repo1.maven.org"))
|
||||||
|
|
||||||
val repos = RepositoriesParser(file)
|
val repos = RepositoriesParser(file)
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,9 @@ import sbt.util._
|
||||||
import sbt.internal.util._
|
import sbt.internal.util._
|
||||||
|
|
||||||
object TestLogger {
|
object TestLogger {
|
||||||
def apply[T](f: Logger => T): T =
|
def apply[T](f: Logger => T): T = {
|
||||||
{
|
val log = new BufferedLogger(ConsoleLogger())
|
||||||
val log = new BufferedLogger(ConsoleLogger())
|
log.setLevel(Level.Debug)
|
||||||
log.setLevel(Level.Debug)
|
log.bufferQuietly(f(log))
|
||||||
log.bufferQuietly(f(log))
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@ object AutomateScalafmtPlugin extends AutoPlugin {
|
||||||
configurations.flatMap { c =>
|
configurations.flatMap { c =>
|
||||||
inConfig(c)(
|
inConfig(c)(
|
||||||
Seq(
|
Seq(
|
||||||
compileInputs.in(compile) := {
|
compileInputs.in(compile) := {
|
||||||
scalafmtInc.value
|
scalafmtInc.value
|
||||||
compileInputs.in(compile).value
|
compileInputs.in(compile).value
|
||||||
},
|
},
|
||||||
sourceDirectories.in(scalafmtInc) := Seq(scalaSource.value),
|
sourceDirectories.in(scalafmtInc) := Seq(scalaSource.value),
|
||||||
scalafmtInc := {
|
scalafmtInc := {
|
||||||
val cache = streams.value.cacheDirectory / "scalafmt"
|
val cache = streams.value.cacheDirectory / "scalafmt"
|
||||||
val include = includeFilter.in(scalafmtInc).value
|
val include = includeFilter.in(scalafmtInc).value
|
||||||
val exclude = excludeFilter.in(scalafmtInc).value
|
val exclude = excludeFilter.in(scalafmtInc).value
|
||||||
val sources =
|
val sources =
|
||||||
|
|
|
||||||
|
|
@ -19,27 +19,39 @@ object DatatypeConfig {
|
||||||
|
|
||||||
/** Codecs that were manually written. */
|
/** Codecs that were manually written. */
|
||||||
val myCodecs: PartialFunction[String, Type => List[String]] = {
|
val myCodecs: PartialFunction[String, Type => List[String]] = {
|
||||||
case "scala.xml.NodeSeq" => { _ => "sbt.internal.librarymanagement.formats.NodeSeqFormat" :: Nil }
|
case "scala.xml.NodeSeq" => { _ =>
|
||||||
|
"sbt.internal.librarymanagement.formats.NodeSeqFormat" :: Nil
|
||||||
|
}
|
||||||
|
|
||||||
case "org.apache.ivy.plugins.resolver.DependencyResolver" =>
|
case "org.apache.ivy.plugins.resolver.DependencyResolver" => { _ =>
|
||||||
{ _ => "sbt.internal.librarymanagement.formats.DependencyResolverFormat" :: Nil }
|
"sbt.internal.librarymanagement.formats.DependencyResolverFormat" :: Nil
|
||||||
|
}
|
||||||
|
|
||||||
case "xsbti.GlobalLock" => { _ => "sbt.internal.librarymanagement.formats.GlobalLockFormat" :: Nil }
|
case "xsbti.GlobalLock" => { _ =>
|
||||||
case "xsbti.Logger" => { _ => "sbt.internal.librarymanagement.formats.LoggerFormat" :: Nil }
|
"sbt.internal.librarymanagement.formats.GlobalLockFormat" :: Nil
|
||||||
|
}
|
||||||
|
case "xsbti.Logger" => { _ =>
|
||||||
|
"sbt.internal.librarymanagement.formats.LoggerFormat" :: Nil
|
||||||
|
}
|
||||||
|
|
||||||
case "sbt.librarymanagement.UpdateOptions" =>
|
case "sbt.librarymanagement.UpdateOptions" => { _ =>
|
||||||
{ _ => "sbt.internal.librarymanagement.formats.UpdateOptionsFormat" :: Nil }
|
"sbt.internal.librarymanagement.formats.UpdateOptionsFormat" :: Nil
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: These are handled by BasicJsonProtocol, and sbt-datatype should handle them by default, imo
|
// TODO: These are handled by BasicJsonProtocol, and sbt-datatype should handle them by default, imo
|
||||||
case "Option" | "Set" | "scala.Vector" => { tpe => getFormats(oneArg(tpe)) }
|
case "Option" | "Set" | "scala.Vector" => { tpe =>
|
||||||
case "Map" | "Tuple2" | "scala.Tuple2" => { tpe => twoArgs(tpe).flatMap(getFormats) }
|
getFormats(oneArg(tpe))
|
||||||
case "Int" | "Long" => { _ => Nil }
|
}
|
||||||
|
case "Map" | "Tuple2" | "scala.Tuple2" => { tpe =>
|
||||||
|
twoArgs(tpe).flatMap(getFormats)
|
||||||
|
}
|
||||||
|
case "Int" | "Long" => { _ =>
|
||||||
|
Nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Types for which we don't include the format -- they're just aliases to InclExclRule */
|
/** Types for which we don't include the format -- they're just aliases to InclExclRule */
|
||||||
val excluded = Set(
|
val excluded = Set("sbt.librarymanagement.InclusionRule", "sbt.librarymanagement.ExclusionRule")
|
||||||
"sbt.librarymanagement.InclusionRule",
|
|
||||||
"sbt.librarymanagement.ExclusionRule")
|
|
||||||
|
|
||||||
/** Returns the list of formats required to encode the given `TpeRef`. */
|
/** Returns the list of formats required to encode the given `TpeRef`. */
|
||||||
val getFormats: Type => List[String] =
|
val getFormats: Type => List[String] =
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,10 @@ object Dependencies {
|
||||||
private val sbtIO = "org.scala-sbt" %% "io" % ioVersion
|
private val sbtIO = "org.scala-sbt" %% "io" % ioVersion
|
||||||
|
|
||||||
private val utilCollection = "org.scala-sbt" %% "util-collection" % utilVersion
|
private val utilCollection = "org.scala-sbt" %% "util-collection" % utilVersion
|
||||||
private val utilLogging = "org.scala-sbt" %% "util-logging" % utilVersion
|
private val utilLogging = "org.scala-sbt" %% "util-logging" % utilVersion
|
||||||
private val utilTesting = "org.scala-sbt" %% "util-testing" % utilVersion
|
private val utilTesting = "org.scala-sbt" %% "util-testing" % utilVersion
|
||||||
private val utilCompletion = "org.scala-sbt" %% "util-completion" % utilVersion
|
private val utilCompletion = "org.scala-sbt" %% "util-completion" % utilVersion
|
||||||
private val utilCache = "org.scala-sbt" %% "util-cache" % utilVersion
|
private val utilCache = "org.scala-sbt" %% "util-cache" % utilVersion
|
||||||
|
|
||||||
def getSbtModulePath(key: String, name: String) = {
|
def getSbtModulePath(key: String, name: String) = {
|
||||||
val localProps = new java.util.Properties()
|
val localProps = new java.util.Properties()
|
||||||
|
|
@ -24,21 +24,31 @@ object Dependencies {
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy val sbtIoPath = getSbtModulePath("sbtio.path", "sbt/io")
|
lazy val sbtIoPath = getSbtModulePath("sbtio.path", "sbt/io")
|
||||||
lazy val sbtUtilPath = getSbtModulePath("sbtutil.path", "sbt/util")
|
lazy val sbtUtilPath = getSbtModulePath("sbtutil.path", "sbt/util")
|
||||||
|
|
||||||
def addSbtModule(p: Project, path: Option[String], projectName: String, m: ModuleID, c: Option[Configuration] = None) =
|
def addSbtModule(p: Project,
|
||||||
|
path: Option[String],
|
||||||
|
projectName: String,
|
||||||
|
m: ModuleID,
|
||||||
|
c: Option[Configuration] = None) =
|
||||||
path match {
|
path match {
|
||||||
case Some(f) => p dependsOn c.fold[ClasspathDependency](ProjectRef(file(f), projectName))(ProjectRef(file(f), projectName) % _)
|
case Some(f) =>
|
||||||
case None => p settings (libraryDependencies += c.fold(m)(m % _))
|
p dependsOn c.fold[ClasspathDependency](ProjectRef(file(f), projectName))(
|
||||||
|
ProjectRef(file(f), projectName) % _)
|
||||||
|
case None => p settings (libraryDependencies += c.fold(m)(m % _))
|
||||||
}
|
}
|
||||||
|
|
||||||
def addSbtIO(p: Project): Project = addSbtModule(p, sbtIoPath, "io", sbtIO)
|
def addSbtIO(p: Project): Project = addSbtModule(p, sbtIoPath, "io", sbtIO)
|
||||||
def addSbtUtilCollection(p: Project): Project = addSbtModule(p, sbtUtilPath, "utilCollection", utilCollection)
|
def addSbtUtilCollection(p: Project): Project =
|
||||||
def addSbtUtilLogging(p: Project): Project = addSbtModule(p, sbtUtilPath, "utilLogging", utilLogging)
|
addSbtModule(p, sbtUtilPath, "utilCollection", utilCollection)
|
||||||
def addSbtUtilTesting(p: Project): Project = addSbtModule(p, sbtUtilPath, "utilTesting", utilTesting, Some(Test))
|
def addSbtUtilLogging(p: Project): Project =
|
||||||
def addSbtUtilCompletion(p: Project): Project = addSbtModule(p, sbtUtilPath, "utilComplete", utilCompletion)
|
addSbtModule(p, sbtUtilPath, "utilLogging", utilLogging)
|
||||||
def addSbtUtilCache(p: Project): Project = addSbtModule(p, sbtUtilPath, "utilCache", utilCache)
|
def addSbtUtilTesting(p: Project): Project =
|
||||||
|
addSbtModule(p, sbtUtilPath, "utilTesting", utilTesting, Some(Test))
|
||||||
|
def addSbtUtilCompletion(p: Project): Project =
|
||||||
|
addSbtModule(p, sbtUtilPath, "utilComplete", utilCompletion)
|
||||||
|
def addSbtUtilCache(p: Project): Project = addSbtModule(p, sbtUtilPath, "utilCache", utilCache)
|
||||||
|
|
||||||
val launcherInterface = "org.scala-sbt" % "launcher-interface" % "1.0.0"
|
val launcherInterface = "org.scala-sbt" % "launcher-interface" % "1.0.0"
|
||||||
val ivy = "org.scala-sbt.ivy" % "ivy" % "2.3.0-sbt-48dd0744422128446aee9ac31aa356ee203cc9f4"
|
val ivy = "org.scala-sbt.ivy" % "ivy" % "2.3.0-sbt-48dd0744422128446aee9ac31aa356ee203cc9f4"
|
||||||
|
|
@ -52,7 +62,7 @@ object Dependencies {
|
||||||
Def.setting {
|
Def.setting {
|
||||||
scalaVersion.value match {
|
scalaVersion.value match {
|
||||||
case sv if (sv startsWith "2.9.") || (sv startsWith "2.10.") => Nil
|
case sv if (sv startsWith "2.9.") || (sv startsWith "2.10.") => Nil
|
||||||
case _ => ("org.scala-lang.modules" %% name % moduleVersion) :: Nil
|
case _ => ("org.scala-lang.modules" %% name % moduleVersion) :: Nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,29 +4,31 @@ import sbt.IO
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
object Util {
|
object Util {
|
||||||
|
|
||||||
def versionLine(version: String): String = "version=" + version
|
def versionLine(version: String): String = "version=" + version
|
||||||
def containsVersion(propFile: File, version: String): Boolean = IO.read(propFile).contains(versionLine(version))
|
def containsVersion(propFile: File, version: String): Boolean =
|
||||||
def lastCompilationTime(analysis: sbt.inc.Analysis): Long =
|
IO.read(propFile).contains(versionLine(version))
|
||||||
{
|
def lastCompilationTime(analysis: sbt.inc.Analysis): Long = {
|
||||||
val lastCompilation = analysis.compilations.allCompilations.lastOption
|
val lastCompilation = analysis.compilations.allCompilations.lastOption
|
||||||
lastCompilation.map(_.startTime) getOrElse 0L
|
lastCompilation.map(_.startTime) getOrElse 0L
|
||||||
}
|
}
|
||||||
|
|
||||||
def generateVersionFile(version: String, dir: File, s: TaskStreams, analysis: sbt.inc.Analysis): Seq[File] =
|
def generateVersionFile(version: String,
|
||||||
{
|
dir: File,
|
||||||
import java.util.{ Date, TimeZone }
|
s: TaskStreams,
|
||||||
val formatter = new java.text.SimpleDateFormat("yyyyMMdd'T'HHmmss")
|
analysis: sbt.inc.Analysis): Seq[File] = {
|
||||||
formatter.setTimeZone(TimeZone.getTimeZone("GMT"))
|
import java.util.{ Date, TimeZone }
|
||||||
val timestamp = formatter.format(new Date)
|
val formatter = new java.text.SimpleDateFormat("yyyyMMdd'T'HHmmss")
|
||||||
val content = versionLine(version) + "\ntimestamp=" + timestamp
|
formatter.setTimeZone(TimeZone.getTimeZone("GMT"))
|
||||||
val f = dir / "xsbt.version.properties"
|
val timestamp = formatter.format(new Date)
|
||||||
if (!f.exists || f.lastModified < lastCompilationTime(analysis) || !containsVersion(f, version)) {
|
val content = versionLine(version) + "\ntimestamp=" + timestamp
|
||||||
s.log.info("Writing version information to " + f + " :\n" + content)
|
val f = dir / "xsbt.version.properties"
|
||||||
IO.write(f, content)
|
if (!f.exists || f.lastModified < lastCompilationTime(analysis) || !containsVersion(f,
|
||||||
}
|
version)) {
|
||||||
f :: Nil
|
s.log.info("Writing version information to " + f + " :\n" + content)
|
||||||
|
IO.write(f, content)
|
||||||
}
|
}
|
||||||
|
f :: Nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.2")
|
addSbtPlugin("org.scala-sbt" % "sbt-houserules" % "0.3.2")
|
||||||
addSbtPlugin("com.eed3si9n" % "sbt-doge" % "0.1.3")
|
addSbtPlugin("com.eed3si9n" % "sbt-doge" % "0.1.3")
|
||||||
addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.0-M4")
|
addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.0-M4")
|
||||||
addSbtPlugin("me.lessis" % "bintray-sbt" % "0.3.0")
|
addSbtPlugin("me.lessis" % "bintray-sbt" % "0.3.0")
|
||||||
addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "0.6.8")
|
addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "0.6.8")
|
||||||
|
|
||||||
scalacOptions += "-language:postfixOps"
|
scalacOptions += "-language:postfixOps"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue