Merge pull request #1601 from sbt/wip/circular

Expose Ivy's circular dependency check via UpdateOptions
This commit is contained in:
Josh Suereth 2014-09-16 18:18:44 -04:00
commit 920c875e12
7 changed files with 133 additions and 1 deletions

View File

@ -0,0 +1,27 @@
package sbt
import org.apache.ivy.plugins.circular.{ CircularDependencyStrategy, WarnCircularDependencyStrategy, IgnoreCircularDependencyStrategy, ErrorCircularDependencyStrategy }
/**
* Wrapper around circular dependency strategy.
*/
sealed trait CircularDependencyLevel {
private[sbt] def ivyStrategy: CircularDependencyStrategy
private[sbt] def name: String
override def toString: String = name
}
object CircularDependencyLevel {
val Warn: CircularDependencyLevel = new CircularDependencyLevel {
def ivyStrategy: CircularDependencyStrategy = WarnCircularDependencyStrategy.getInstance
def name: String = "warn"
}
val Ignore: CircularDependencyLevel = new CircularDependencyLevel {
def ivyStrategy: CircularDependencyStrategy = IgnoreCircularDependencyStrategy.getInstance
def name: String = "ignore"
}
val Error: CircularDependencyLevel = new CircularDependencyLevel {
def ivyStrategy: CircularDependencyStrategy = ErrorCircularDependencyStrategy.getInstance
def name: String = "error"
}
}

View File

@ -69,6 +69,7 @@ final class IvySbt(val configuration: IvyConfiguration) {
{
val is = new IvySettings
is.setBaseDir(baseDirectory)
is.setCircularDependencyStrategy(configuration.updateOptions.circularDependencyLevel.ivyStrategy)
CustomPomParser.registerDefault
configuration match {
case e: ExternalIvyConfiguration =>

View File

@ -10,25 +10,33 @@ import java.io.File
* See also UpdateConfiguration in IvyActions.scala.
*/
final class UpdateOptions private[sbt] (
/** If set to CircularDependencyLevel.Error, halt the dependency resolution. */
val circularDependencyLevel: CircularDependencyLevel,
/** If set to true, check all resolvers for snapshots. */
val latestSnapshots: Boolean,
/** If set to true, use consolidated resolution. */
val consolidatedResolution: Boolean) {
def withCircularDependencyLevel(circularDependencyLevel: CircularDependencyLevel): UpdateOptions =
copy(circularDependencyLevel = circularDependencyLevel)
def withLatestSnapshots(latestSnapshots: Boolean): UpdateOptions =
copy(latestSnapshots = latestSnapshots)
def withConsolidatedResolution(consolidatedResolution: Boolean): UpdateOptions =
copy(consolidatedResolution = consolidatedResolution)
private[sbt] def copy(
circularDependencyLevel: CircularDependencyLevel = this.circularDependencyLevel,
latestSnapshots: Boolean = this.latestSnapshots,
consolidatedResolution: Boolean = this.consolidatedResolution): UpdateOptions =
new UpdateOptions(latestSnapshots, consolidatedResolution)
new UpdateOptions(circularDependencyLevel,
latestSnapshots,
consolidatedResolution)
}
object UpdateOptions {
def apply(): UpdateOptions =
new UpdateOptions(
circularDependencyLevel = CircularDependencyLevel.Warn,
latestSnapshots = true,
consolidatedResolution = false)
}

View File

@ -0,0 +1,7 @@
[@eed3si9n]: https://github.com/eed3si9n
### Circular dependency
By default circular dependencies are warned, but they do not halt the dependency resolution. Using the following setting, circular dependencies can be treated as an error.
updateOptions := updateOptions.value.withCircularDependencyLevel(CircularDependencyLevel.Error)

View File

@ -0,0 +1,40 @@
lazy val check = taskKey[Unit]("Runs the check")
def commonSettings: Seq[Def.Setting[_]] =
Seq(
ivyPaths := new IvyPaths( (baseDirectory in ThisBuild).value, Some((target in LocalRootProject).value / "ivy-cache")),
scalaVersion := "2.10.4",
updateOptions := updateOptions.value.withCircularDependencyLevel(CircularDependencyLevel.Error)
)
lazy val a = project.
settings(commonSettings: _*).
settings(
name := "a",
libraryDependencies := Seq(
"commons-io" % "commons-io" % "1.3",
organization.value %% "c" % version.value
)
)
lazy val b = project.
settings(commonSettings: _*).
settings(
name := "b",
// this adds circular dependency
libraryDependencies := Seq(organization.value %% "c" % version.value)
)
lazy val c = project.
settings(commonSettings: _*).
settings(
name := "c",
libraryDependencies := Seq(organization.value %% "b" % version.value)
)
lazy val root = (project in file(".")).
settings(commonSettings: _*).
settings(
organization in ThisBuild := "org.example",
version in ThisBuild := "1.0-SNAPSHOT"
)

View File

@ -0,0 +1,36 @@
lazy val check = taskKey[Unit]("Runs the check")
def commonSettings: Seq[Def.Setting[_]] =
Seq(
ivyPaths := new IvyPaths( (baseDirectory in ThisBuild).value, Some((target in LocalRootProject).value / "ivy-cache")),
scalaVersion := "2.10.4"
)
lazy val a = project.
settings(commonSettings: _*).
settings(
name := "a",
libraryDependencies := Seq(
"commons-io" % "commons-io" % "1.3"
)
)
lazy val b = project.
settings(commonSettings: _*).
settings(
name := "b"
)
lazy val c = project.
settings(commonSettings: _*).
settings(
name := "c",
libraryDependencies := Seq(organization.value %% "b" % version.value)
)
lazy val root = (project in file(".")).
settings(commonSettings: _*).
settings(
organization in ThisBuild := "org.example",
version in ThisBuild := "1.0-SNAPSHOT"
)

View File

@ -0,0 +1,13 @@
> a/publishLocal
> b/publishLocal
> c/publishLocal
$ copy-file changes/multi.sbt multi.sbt
> reload
-> b/publishLocal
> a/publishLocal