summaryrefslogtreecommitdiff
path: root/scalalib
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2018-04-06 19:40:03 -0700
committerLi Haoyi <haoyi.sg@gmail.com>2018-04-06 19:40:03 -0700
commitb9e9b6827da900a1c3565ebbd4a18f1657d6114c (patch)
tree5bf2e1239f9fed2490a6af791b6f1fb81b76e3d3 /scalalib
parent26865c6623d57b7a5d774c7bbfe5897609e11acf (diff)
downloadmill-b9e9b6827da900a1c3565ebbd4a18f1657d6114c.tar.gz
mill-b9e9b6827da900a1c3565ebbd4a18f1657d6114c.tar.bz2
mill-b9e9b6827da900a1c3565ebbd4a18f1657d6114c.zip
basic support for version pinning (used by default for scala-library/compiler) and for typelevel scala
Diffstat (limited to 'scalalib')
-rw-r--r--scalalib/src/mill/scalalib/Dep.scala62
-rw-r--r--scalalib/src/mill/scalalib/Lib.scala49
-rw-r--r--scalalib/src/mill/scalalib/ScalaModule.scala27
-rw-r--r--scalalib/src/mill/scalalib/publish/settings.scala6
-rw-r--r--scalalib/test/src/mill/scalalib/HelloWorldTests.scala37
5 files changed, 126 insertions, 55 deletions
diff --git a/scalalib/src/mill/scalalib/Dep.scala b/scalalib/src/mill/scalalib/Dep.scala
index f20480b7..84aa6576 100644
--- a/scalalib/src/mill/scalalib/Dep.scala
+++ b/scalalib/src/mill/scalalib/Dep.scala
@@ -3,20 +3,24 @@ import mill.util.JsonFormatters._
import upickle.default.{macroRW, ReadWriter => RW}
sealed trait Dep {
def configure(attributes: coursier.Attributes): Dep
- def exclude(exclusions: (String, String)*): Dep =
- this match {
- case dep : Dep.Java => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
- case dep : Dep.Scala => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
- case dep : Dep.Point => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
- }
+ def force: Boolean
+ def forceVersion(): Dep = this match {
+ case dep : Dep.Java => dep.copy(force = true)
+ case dep : Dep.Scala => dep.copy(force = true)
+ case dep : Dep.Point => dep.copy(force = true)
+ }
+ def exclude(exclusions: (String, String)*): Dep = this match {
+ case dep : Dep.Java => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
+ case dep : Dep.Scala => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
+ case dep : Dep.Point => dep.copy(dep = dep.dep.copy(exclusions = dep.dep.exclusions ++ exclusions))
+ }
def excludeOrg(organizations: String*): Dep = exclude(organizations.map(_ -> "*"): _*)
def excludeName(names: String*): Dep = exclude(names.map("*" -> _): _*)
- def withConfiguration(configuration: String): Dep =
- this match {
- case dep : Dep.Java => dep.copy(dep = dep.dep.copy(configuration = configuration))
- case dep : Dep.Scala => dep.copy(dep = dep.dep.copy(configuration = configuration))
- case dep : Dep.Point => dep.copy(dep = dep.dep.copy(configuration = configuration))
- }
+ def withConfiguration(configuration: String): Dep = this match {
+ case dep : Dep.Java => dep.copy(dep = dep.dep.copy(configuration = configuration))
+ case dep : Dep.Scala => dep.copy(dep = dep.dep.copy(configuration = configuration))
+ case dep : Dep.Point => dep.copy(dep = dep.dep.copy(configuration = configuration))
+ }
}
object Dep{
@@ -31,45 +35,45 @@ object Dep{
}
}
(module.split(':') match {
- case Array(a, b, c) => Dep.Java(a, b, c, cross = false)
- case Array(a, b, "", c) => Dep.Java(a, b, c, cross = true)
- case Array(a, "", b, c) => Dep.Scala(a, b, c, cross = false)
- case Array(a, "", b, "", c) => Dep.Scala(a, b, c, cross = true)
- case Array(a, "", "", b, c) => Dep.Point(a, b, c, cross = false)
- case Array(a, "", "", b, "", c) => Dep.Point(a, b, c, cross = true)
+ case Array(a, b, c) => Dep.Java(a, b, c, cross = false, force = false)
+ case Array(a, b, "", c) => Dep.Java(a, b, c, cross = true, force = false)
+ case Array(a, "", b, c) => Dep.Scala(a, b, c, cross = false, force = false)
+ case Array(a, "", b, "", c) => Dep.Scala(a, b, c, cross = true, force = false)
+ case Array(a, "", "", b, c) => Dep.Point(a, b, c, cross = false, force = false)
+ case Array(a, "", "", b, "", c) => Dep.Point(a, b, c, cross = true, force = false)
case _ => throw new Exception(s"Unable to parse signature: [$signature]")
}).configure(attributes = attributes)
}
def apply(org: String, name: String, version: String, cross: Boolean): Dep = {
this(coursier.Dependency(coursier.Module(org, name), version), cross)
}
- case class Java(dep: coursier.Dependency, cross: Boolean) extends Dep {
+ case class Java(dep: coursier.Dependency, cross: Boolean, force: Boolean) extends Dep {
def configure(attributes: coursier.Attributes): Dep = copy(dep = dep.copy(attributes = attributes))
}
object Java{
implicit def rw: RW[Java] = macroRW
- def apply(org: String, name: String, version: String, cross: Boolean): Dep = {
- Java(coursier.Dependency(coursier.Module(org, name), version), cross)
+ def apply(org: String, name: String, version: String, cross: Boolean, force: Boolean): Dep = {
+ Java(coursier.Dependency(coursier.Module(org, name), version), cross, force)
}
}
- implicit def default(dep: coursier.Dependency): Dep = new Java(dep, false)
- def apply(dep: coursier.Dependency, cross: Boolean) = Scala(dep, cross)
- case class Scala(dep: coursier.Dependency, cross: Boolean) extends Dep {
+ implicit def default(dep: coursier.Dependency): Dep = new Java(dep, false, false)
+ def apply(dep: coursier.Dependency, cross: Boolean) = Scala(dep, cross, false)
+ case class Scala(dep: coursier.Dependency, cross: Boolean, force: Boolean) extends Dep {
def configure(attributes: coursier.Attributes): Dep = copy(dep = dep.copy(attributes = attributes))
}
object Scala{
implicit def rw: RW[Scala] = macroRW
- def apply(org: String, name: String, version: String, cross: Boolean): Dep = {
- Scala(coursier.Dependency(coursier.Module(org, name), version), cross)
+ def apply(org: String, name: String, version: String, cross: Boolean, force: Boolean): Dep = {
+ Scala(coursier.Dependency(coursier.Module(org, name), version), cross, force)
}
}
- case class Point(dep: coursier.Dependency, cross: Boolean) extends Dep {
+ case class Point(dep: coursier.Dependency, cross: Boolean, force: Boolean) extends Dep {
def configure(attributes: coursier.Attributes): Dep = copy(dep = dep.copy(attributes = attributes))
}
object Point{
implicit def rw: RW[Point] = macroRW
- def apply(org: String, name: String, version: String, cross: Boolean): Dep = {
- Point(coursier.Dependency(coursier.Module(org, name), version), cross)
+ def apply(org: String, name: String, version: String, cross: Boolean, force: Boolean): Dep = {
+ Point(coursier.Dependency(coursier.Module(org, name), version), cross, force)
}
}
implicit def rw = RW.merge[Dep](
diff --git a/scalalib/src/mill/scalalib/Lib.scala b/scalalib/src/mill/scalalib/Lib.scala
index e6a7a255..46296333 100644
--- a/scalalib/src/mill/scalalib/Lib.scala
+++ b/scalalib/src/mill/scalalib/Lib.scala
@@ -36,7 +36,7 @@ object Lib{
def depToDependency(dep: Dep, scalaVersion: String, platformSuffix: String = ""): Dependency =
dep match {
- case Dep.Java(dep, cross) =>
+ case Dep.Java(dep, cross, force) =>
dep.copy(
module = dep.module.copy(
name =
@@ -44,7 +44,7 @@ object Lib{
(if (!cross) "" else platformSuffix)
)
)
- case Dep.Scala(dep, cross) =>
+ case Dep.Scala(dep, cross, force) =>
dep.copy(
module = dep.module.copy(
name =
@@ -53,7 +53,7 @@ object Lib{
"_" + scalaBinaryVersion(scalaVersion)
)
)
- case Dep.Point(dep, cross) =>
+ case Dep.Point(dep, cross, force) =>
dep.copy(
module = dep.module.copy(
name =
@@ -65,7 +65,30 @@ object Lib{
}
+ def resolveDependenciesMetadata(repositories: Seq[Repository],
+ scalaVersion: String,
+ deps: TraversableOnce[Dep],
+ platformSuffix: String = "",
+ mapDependencies: Option[Dependency => Dependency] = None) = {
+ val depSeq = deps.toSeq
+ val flattened = depSeq.map(depToDependency(_, scalaVersion, platformSuffix))
+
+ val forceVersions = depSeq.filter(_.force)
+ .map(depToDependency(_, scalaVersion, platformSuffix))
+ .map(mapDependencies.getOrElse(identity[Dependency](_)))
+ .map{d => d.module -> d.version}
+ .toMap
+
+ val start = Resolution(
+ flattened.map(mapDependencies.getOrElse(identity[Dependency](_))).toSet,
+ forceVersions = forceVersions,
+ mapDependencies = mapDependencies
+ )
+ val fetch = Fetch.from(repositories, Cache.fetch())
+ val resolution = start.process.run(fetch).unsafePerformSync
+ (flattened, resolution)
+ }
/**
* Resolve dependencies using Coursier.
*
@@ -77,13 +100,12 @@ object Lib{
scalaVersion: String,
deps: TraversableOnce[Dep],
platformSuffix: String = "",
- sources: Boolean = false): Result[Agg[PathRef]] = {
+ sources: Boolean = false,
+ mapDependencies: Option[Dependency => Dependency] = None): Result[Agg[PathRef]] = {
- val flattened = deps.map(depToDependency(_, scalaVersion, platformSuffix)).toSet
- val start = Resolution(flattened)
-
- val fetch = Fetch.from(repositories, Cache.fetch())
- val resolution = start.process.run(fetch).unsafePerformSync
+ val (_, resolution) = resolveDependenciesMetadata(
+ repositories, scalaVersion, deps, platformSuffix, mapDependencies
+ )
val errs = resolution.metadataErrors
if(errs.nonEmpty) {
val header =
@@ -130,16 +152,17 @@ object Lib{
}
}
def scalaCompilerIvyDeps(scalaVersion: String) = Agg[Dep](
- ivy"org.scala-lang:scala-compiler:$scalaVersion",
- ivy"org.scala-lang:scala-reflect:$scalaVersion"
+ ivy"org.scala-lang:scala-compiler:$scalaVersion".forceVersion(),
+ ivy"org.scala-lang:scala-reflect:$scalaVersion".forceVersion()
)
def scalaRuntimeIvyDeps(scalaVersion: String) = Agg[Dep](
- ivy"org.scala-lang:scala-library:$scalaVersion"
+ ivy"org.scala-lang:scala-library:$scalaVersion".forceVersion()
)
def compilerBridgeIvyDep(scalaVersion: String) =
Dep.Point(
coursier.Dependency(coursier.Module("com.lihaoyi", "mill-bridge"), "0.1", transitive = false),
- cross = false
+ cross = false,
+ force = false
)
}
diff --git a/scalalib/src/mill/scalalib/ScalaModule.scala b/scalalib/src/mill/scalalib/ScalaModule.scala
index ed176269..562b60d6 100644
--- a/scalalib/src/mill/scalalib/ScalaModule.scala
+++ b/scalalib/src/mill/scalalib/ScalaModule.scala
@@ -2,7 +2,7 @@ package mill
package scalalib
import ammonite.ops._
-import coursier.Repository
+import coursier.{Dependency, Repository}
import mill.define.Task
import mill.define.TaskModule
import mill.eval.{PathRef, Result}
@@ -86,13 +86,16 @@ trait ScalaModule extends mill.Module with TaskModule { outer =>
)().flatten
}
+ def mapDependencies(d: coursier.Dependency) = d
+
def resolveDeps(deps: Task[Agg[Dep]], sources: Boolean = false) = T.task{
resolveDependencies(
repositories,
scalaVersion(),
deps(),
platformSuffix(),
- sources
+ sources,
+ mapDependencies = Some(mapDependencies)
)
}
@@ -263,12 +266,9 @@ trait ScalaModule extends mill.Module with TaskModule { outer =>
}
def ivyDepsTree(inverse: Boolean = false) = T.command {
- import coursier.{Cache, Fetch, Resolution}
-
- val flattened = ivyDeps().map(depToDependency(_, scalaVersion(), platformSuffix())).toSeq
- val start = Resolution(flattened.toSet)
- val fetch = Fetch.from(repositories, Cache.fetch())
- val resolution = start.process.run(fetch).unsafePerformSync
+ val (flattened, resolution) = Lib.resolveDependenciesMetadata(
+ repositories, scalaVersion(), ivyDeps(), platformSuffix(), Some(mapDependencies)
+ )
println(coursier.util.Print.dependencyTree(flattened, resolution,
printExclusions = false, reverse = inverse))
@@ -330,15 +330,22 @@ trait ScalaModule extends mill.Module with TaskModule { outer =>
}
def ammoniteReplClasspath = T{
- resolveDeps(T.task{Agg(ivy"com.lihaoyi:::ammonite:1.1.0-7-33b728c")})()
+ localClasspath() ++
+ transitiveLocalClasspath() ++
+ unmanagedClasspath() ++
+ resolveDeps(T.task{
+ runIvyDeps() ++ scalaLibraryIvyDeps() ++ transitiveIvyDeps() ++
+ Agg(ivy"com.lihaoyi:::ammonite:1.1.0-7-33b728c")
+ })()
}
+
def repl() = T.command{
if (T.ctx().log.inStream == DummyInputStream){
Result.Failure("repl needs to be run with the -i/--interactive flag")
}else{
Jvm.interactiveSubprocess(
mainClass = "ammonite.Main",
- classPath = runClasspath().map(_.path) ++ ammoniteReplClasspath().map(_.path),
+ classPath = ammoniteReplClasspath().map(_.path),
mainArgs = Nil,
workingDir = pwd
)
diff --git a/scalalib/src/mill/scalalib/publish/settings.scala b/scalalib/src/mill/scalalib/publish/settings.scala
index 34f7e7ad..596f29c9 100644
--- a/scalalib/src/mill/scalalib/publish/settings.scala
+++ b/scalalib/src/mill/scalalib/publish/settings.scala
@@ -12,14 +12,14 @@ object Artifact {
scalaFull: String,
scalaBin: String): Dependency = {
dep match {
- case Dep.Java(dep, cross) =>
+ case Dep.Java(dep, cross, force) =>
Dependency(
Artifact(dep.module.organization, dep.module.name, dep.version),
Scope.Compile,
if (dep.configuration == "" ) None else Some(dep.configuration),
dep.exclusions.toList
)
- case Dep.Scala(dep, cross) =>
+ case Dep.Scala(dep, cross, force) =>
Dependency(
Artifact(
dep.module.organization,
@@ -30,7 +30,7 @@ object Artifact {
if (dep.configuration == "") None else Some(dep.configuration),
dep.exclusions.toList
)
- case Dep.Point(dep, cross) =>
+ case Dep.Point(dep, cross, force) =>
Dependency(
Artifact(
dep.module.organization,
diff --git a/scalalib/test/src/mill/scalalib/HelloWorldTests.scala b/scalalib/test/src/mill/scalalib/HelloWorldTests.scala
index 74078221..d6980314 100644
--- a/scalalib/test/src/mill/scalalib/HelloWorldTests.scala
+++ b/scalalib/test/src/mill/scalalib/HelloWorldTests.scala
@@ -98,6 +98,24 @@ object HelloWorldTests extends TestSuite {
override def ivyDeps = Agg(ivy"com.lihaoyi::sourcecode:0.1.4")
}
}
+
+ object HelloWorldTypeLevel extends HelloBase{
+ object foo extends ScalaModule {
+ def scalaVersion = "2.11.8"
+ override def mapDependencies(d: coursier.Dependency) = {
+ val artifacts = Set("scala-library", "scala-compiler", "scala-reflect")
+ if (d.module.organization != "org.scala-lang" || !artifacts(d.module.name)) d
+ else d.copy(module = d.module.copy(organization = "org.typelevel"))
+ }
+
+ def ivyDeps = Agg(
+ ivy"com.github.julien-truffaut::monocle-macro::1.4.0"
+ )
+ def scalacPluginIvyDeps = super.scalacPluginIvyDeps() ++ Agg(
+ ivy"org.scalamacros:::paradise:2.1.0"
+ )
+ }
+ }
val resourcePath = pwd / 'scalalib / 'test / 'resources / "hello-world"
def jarMainClass(jar: JarFile): Option[String] = {
@@ -438,6 +456,25 @@ object HelloWorldTests extends TestSuite {
!result2.exists(_.path.last == "sourcecode_2.12-0.1.3.jar")
)
}
+ 'typeLevel - workspaceTest(HelloWorldTypeLevel){ eval =>
+ val classPathsToCheck = Seq(
+ HelloWorldTypeLevel.foo.runClasspath,
+ HelloWorldTypeLevel.foo.ammoniteReplClasspath,
+ HelloWorldTypeLevel.foo.compileClasspath
+ )
+ for(cp <- classPathsToCheck){
+ val Right((result, _)) = eval.apply(cp)
+ assert(
+ // Make sure every relevant piece org.scala-lang has been substituted for org.typelevel
+ !result.map(_.toString).exists(x =>
+ x.contains("scala-lang") &&
+ (x.contains("scala-library") || x.contains("scala-compiler") || x.contains("scala-reflect"))
+ ),
+ result.map(_.toString).exists(x => x.contains("typelevel") && x.contains("scala-library"))
+
+ )
+ }
+ }
}