diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2018-04-06 19:40:03 -0700 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2018-04-06 19:40:03 -0700 |
commit | b9e9b6827da900a1c3565ebbd4a18f1657d6114c (patch) | |
tree | 5bf2e1239f9fed2490a6af791b6f1fb81b76e3d3 /scalalib | |
parent | 26865c6623d57b7a5d774c7bbfe5897609e11acf (diff) | |
download | mill-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.scala | 62 | ||||
-rw-r--r-- | scalalib/src/mill/scalalib/Lib.scala | 49 | ||||
-rw-r--r-- | scalalib/src/mill/scalalib/ScalaModule.scala | 27 | ||||
-rw-r--r-- | scalalib/src/mill/scalalib/publish/settings.scala | 6 | ||||
-rw-r--r-- | scalalib/test/src/mill/scalalib/HelloWorldTests.scala | 37 |
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")) + + ) + } + } } |