mirror of https://github.com/sbt/sbt.git
configuration via ivysettings.xml: use URI instead of URL and make 'inter-project' resolver available for multi-project builds. ref #416
This commit is contained in:
parent
53afd56131
commit
7109bc9637
|
|
@ -6,6 +6,7 @@ package sbt
|
|||
import Resolver.PluginPattern
|
||||
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
import java.util.concurrent.Callable
|
||||
import java.util.{Collection, Collections => CS}
|
||||
import CS.singleton
|
||||
|
|
@ -65,7 +66,9 @@ final class IvySbt(val configuration: IvyConfiguration)
|
|||
CustomPomParser.registerDefault
|
||||
configuration match
|
||||
{
|
||||
case e: ExternalIvyConfiguration => is.load(e.url)
|
||||
case e: ExternalIvyConfiguration =>
|
||||
IvySbt.addResolvers(e.extraResolvers, is, configuration.log)
|
||||
IvySbt.loadURI(is, e.uri)
|
||||
case i: InlineIvyConfiguration =>
|
||||
is.setVariable("ivy.checksums", i.checksums mkString ",")
|
||||
i.paths.ivyHome foreach is.setDefaultIvyUserDir
|
||||
|
|
@ -198,6 +201,14 @@ private object IvySbt
|
|||
def defaultIvyConfiguration(project: File) = new File(project, DefaultIvyConfigFilename)
|
||||
def defaultPOM(project: File) = new File(project, DefaultMavenFilename)
|
||||
|
||||
def loadURI(is: IvySettings, uri: URI)
|
||||
{
|
||||
if(uri.getScheme == "file")
|
||||
is.load(new File(uri)) // IVY-1114
|
||||
else
|
||||
is.load(uri.toURL)
|
||||
}
|
||||
|
||||
/** Sets the resolvers for 'settings' to 'resolvers'. This is done by creating a new chain and making it the default.
|
||||
* 'other' is for resolvers that should be in a different chain. These are typically used for publishing or other actions. */
|
||||
private def setResolvers(settings: IvySettings, resolvers: Seq[Resolver], other: Seq[Resolver], localOnly: Boolean, log: Logger)
|
||||
|
|
@ -236,6 +247,13 @@ private object IvySbt
|
|||
}
|
||||
newDefault
|
||||
}
|
||||
def addResolvers(resolvers: Seq[Resolver], settings: IvySettings, log: Logger)
|
||||
{
|
||||
for(r <- resolvers) {
|
||||
log.debug("\t" + r)
|
||||
settings.addResolver(ConvertResolver(r)(settings, log))
|
||||
}
|
||||
}
|
||||
/** A hack to detect if the given artifact is an automatically generated request for a classifier,
|
||||
* as opposed to a user-initiated declaration. It relies on Ivy prefixing classifier with m:, while sbt uses e:.
|
||||
* Clearly, it would be better to have an explicit option in Ivy to control this.*/
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import java.net.{URI,URL}
|
||||
import scala.xml.NodeSeq
|
||||
|
||||
final class IvyPaths(val baseDirectory: File, val ivyHome: Option[File])
|
||||
|
|
@ -28,20 +28,21 @@ final class InlineIvyConfiguration(val paths: IvyPaths, val resolvers: Seq[Resol
|
|||
def withBase(newBase: File) = new InlineIvyConfiguration(paths.withBase(newBase), resolvers, otherResolvers, moduleConfigurations, localOnly, lock, checksums, log)
|
||||
def changeResolvers(newResolvers: Seq[Resolver]) = new InlineIvyConfiguration(paths, newResolvers, otherResolvers, moduleConfigurations, localOnly, lock, checksums, log)
|
||||
}
|
||||
final class ExternalIvyConfiguration(val baseDirectory: File, val url: URL, val lock: Option[xsbti.GlobalLock], val log: Logger) extends IvyConfiguration
|
||||
final class ExternalIvyConfiguration(val baseDirectory: File, val uri: URI, val lock: Option[xsbti.GlobalLock], val extraResolvers: Seq[Resolver], val log: Logger) extends IvyConfiguration
|
||||
{
|
||||
type This = ExternalIvyConfiguration
|
||||
def withBase(newBase: File) = new ExternalIvyConfiguration(newBase, url, lock, log)
|
||||
def withBase(newBase: File) = new ExternalIvyConfiguration(newBase, uri, lock, extraResolvers, log)
|
||||
}
|
||||
object ExternalIvyConfiguration
|
||||
{
|
||||
def apply(baseDirectory: File, file: File, lock: Option[xsbti.GlobalLock], log: Logger) = new ExternalIvyConfiguration(baseDirectory, file.toURI.toURL, lock, log)
|
||||
def apply(baseDirectory: File, file: File, lock: Option[xsbti.GlobalLock], log: Logger) = new ExternalIvyConfiguration(baseDirectory, file.toURI, lock, Nil, log)
|
||||
}
|
||||
|
||||
object IvyConfiguration
|
||||
{
|
||||
/** Called to configure Ivy when inline resolvers are not specified.
|
||||
* This will configure Ivy with an 'ivy-settings.xml' file if there is one or else use default resolvers.*/
|
||||
@deprecated("Explicitly use either external or inline configuration.", "0.12.0")
|
||||
def apply(paths: IvyPaths, lock: Option[xsbti.GlobalLock], localOnly: Boolean, checksums: Seq[String], log: Logger): IvyConfiguration =
|
||||
{
|
||||
log.debug("Autodetecting configuration.")
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ package sbt
|
|||
import org.apache.ivy.core.module.{descriptor, id}
|
||||
import descriptor.ModuleDescriptor, id.ModuleRevisionId
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import java.net.{URI,URL}
|
||||
import java.util.concurrent.Callable
|
||||
import sbinary.DefaultProtocol.StringFormat
|
||||
import Cache.seqFormat
|
||||
|
|
@ -1251,14 +1251,17 @@ trait BuildExtra extends BuildCommon
|
|||
|
||||
def seq(settings: Setting[_]*): SettingsDefinition = new Project.SettingList(settings)
|
||||
|
||||
def externalIvySettings(file: Initialize[File] = baseDirectory / "ivysettings.xml"): Setting[Task[IvyConfiguration]] =
|
||||
externalIvySettingsUrl(file(_.toURI.toURL))
|
||||
def externalIvySettings(url: URL): Setting[Task[IvyConfiguration]] = externalIvySettingsUrl(new Project.Value(() => url))
|
||||
private def externalIvySettingsUrl(url: Initialize[URL]): Setting[Task[IvyConfiguration]] =
|
||||
def externalIvySettings(file: Initialize[File] = baseDirectory / "ivysettings.xml", addMultiResolver: Boolean = true): Setting[Task[IvyConfiguration]] =
|
||||
externalIvySettingsURI(file(_.toURI), addMultiResolver)
|
||||
def externalIvySettingsURL(url: URL, addMultiResolver: Boolean = true): Setting[Task[IvyConfiguration]] =
|
||||
externalIvySettingsURI(Project.value(url.toURI), addMultiResolver)
|
||||
def externalIvySettingsURI(uri: Initialize[URI], addMultiResolver: Boolean = true): Setting[Task[IvyConfiguration]] =
|
||||
{
|
||||
val other = (baseDirectory, appConfiguration, streams).identityMap
|
||||
ivyConfiguration <<= (url zipWith other) { case (u, otherTask) =>
|
||||
otherTask map { case (base, app, s) => new ExternalIvyConfiguration(base, u, Some(lock(app)), s.log) }
|
||||
val other = (baseDirectory, appConfiguration, projectResolver, streams).identityMap
|
||||
ivyConfiguration <<= (uri zipWith other) { case (u, otherTask) =>
|
||||
otherTask map { case (base, app, pr, s) =>
|
||||
val extraResolvers = if(addMultiResolver) pr :: Nil else Nil
|
||||
new ExternalIvyConfiguration(base, u, Some(lock(app)), extraResolvers, s.log) }
|
||||
}
|
||||
}
|
||||
def externalIvyFile(file: Initialize[File] = baseDirectory / "ivy.xml", iScala: Initialize[Option[IvyScala]] = ivyScala): Setting[Task[ModuleSettings]] =
|
||||
|
|
|
|||
|
|
@ -186,11 +186,7 @@ object CacheIvy
|
|||
implicit def fileConfToHL = (f: FileConfiguration) => f.isLocal :+: f.isTransactional :+: HNil
|
||||
|
||||
implicit def externalIvyConfigurationToHL = (e: ExternalIvyConfiguration) =>
|
||||
exists(e.baseDirectory) :+:
|
||||
(e.url match {
|
||||
case u: URL if u.getProtocol == "file" => Hash(u)
|
||||
case u: URL => Hash(u.toURI.normalize.toString)
|
||||
}) :+: HNil
|
||||
exists(e.baseDirectory) :+: Hash.contentsIfLocal(e.uri) :+: HNil
|
||||
}
|
||||
import L1._
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
<ivysettings>
|
||||
<caches defaultCacheDir="${ivy.settings.dir}/target/use-cache" useOrigin="true"/>
|
||||
<settings defaultResolver="test-chain"/>
|
||||
<resolvers>
|
||||
<ibiblio name="central" m2compatible="true"/>
|
||||
<chain name="test-chain" returnFirst="true" checkmodified="true">
|
||||
<resolver ref="inter-project"/>
|
||||
<resolver ref="central"/>
|
||||
</chain>
|
||||
</resolvers>
|
||||
</ivysettings>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
object D {
|
||||
val x = 3
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import sbt._
|
||||
import Keys._
|
||||
|
||||
object B extends Build
|
||||
{
|
||||
lazy val dep = Project("dep", file("dep")) settings( baseSettings : _*) settings(
|
||||
organization := "org.example",
|
||||
version := "1.0"
|
||||
)
|
||||
lazy val use = Project("use", file("use")) dependsOn(dep) settings(baseSettings : _*) settings(
|
||||
libraryDependencies += "junit" % "junit" % "4.5",
|
||||
externalIvySettings()
|
||||
)
|
||||
lazy val baseSettings = Seq(
|
||||
autoScalaLibrary := false,
|
||||
unmanagedJars in Compile <++= scalaInstance map (_.jars)
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
-> use/compile
|
||||
$ copy-file changes/ivysettings.xml use/ivysettings.xml
|
||||
> use/compile
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import junit._
|
||||
|
||||
object U {
|
||||
val x = D.x
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<ivysettings>
|
||||
<caches defaultCacheDir="${ivy.settings.dir}/target/use-cache" useOrigin="true"/>
|
||||
<settings defaultResolver="test-chain"/>
|
||||
<resolvers>
|
||||
<ibiblio name="central" m2compatible="true"/>
|
||||
<chain name="test-chain" returnFirst="true" checkmodified="true">
|
||||
<resolver ref="central"/>
|
||||
</chain>
|
||||
</resolvers>
|
||||
</ivysettings>
|
||||
|
|
@ -0,0 +1 @@
|
|||
object A { val x = B.x }
|
||||
|
|
@ -0,0 +1 @@
|
|||
object B { val x = 3 }
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<ivysettings>
|
||||
<settings defaultResolver="multi-test-chain"/>
|
||||
<include url="${ivy.default.settings.dir}/ivysettings-public.xml"/>
|
||||
<include url="${ivy.default.settings.dir}/ivysettings-local.xml"/>
|
||||
|
||||
<resolvers>
|
||||
<chain name="multi-test-chain" returnFirst="true" checkmodified="false">
|
||||
<resolver ref="inter-project"/>
|
||||
<resolver ref="local"/>
|
||||
<resolver ref="public"/>
|
||||
</chain>
|
||||
</resolvers>
|
||||
</ivysettings>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import sbt._
|
||||
import Keys._
|
||||
|
||||
object Build extends Build
|
||||
{
|
||||
lazy val a = Project("a", file(".")) settings(externalIvySettings()) dependsOn(b)
|
||||
lazy val b = Project("b", file("b")) settings(externalIvySettings( (baseDirectory in ThisBuild) / "ivysettings.xml" ))
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
> compile
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
package sbt
|
||||
|
||||
import java.io.{ByteArrayInputStream, File, InputStream}
|
||||
import java.net.URL
|
||||
import java.net.{URI,URL}
|
||||
|
||||
object Hash
|
||||
{
|
||||
|
|
@ -45,6 +45,13 @@ object Hash
|
|||
def apply(file: File): Array[Byte] = Using.fileInputStream(file)(apply)
|
||||
/** Calculates the SHA-1 hash of the given resource.*/
|
||||
def apply(url: URL): Array[Byte] = Using.urlInputStream(url)(apply)
|
||||
|
||||
/** If the URI represents a local file (the scheme is "file"),
|
||||
* this method calculates the SHA-1 hash of the contents of that file.
|
||||
* Otherwise, this methods calculates the SHA-1 hash of the normalized string representation of the URI.*/
|
||||
def contentsIfLocal(uri: URI): Array[Byte] =
|
||||
if(uri.getScheme == "file") apply(uri.toURL) else apply(uri.normalize.toString)
|
||||
|
||||
/** Calculates the SHA-1 hash of the given stream, closing it when finished.*/
|
||||
def apply(stream: InputStream): Array[Byte] =
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue