From b9e9b6827da900a1c3565ebbd4a18f1657d6114c Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 6 Apr 2018 19:40:03 -0700 Subject: basic support for version pinning (used by default for scala-library/compiler) and for typelevel scala --- scalalib/src/mill/scalalib/Dep.scala | 62 ++++++++++++----------- scalalib/src/mill/scalalib/Lib.scala | 49 +++++++++++++----- scalalib/src/mill/scalalib/ScalaModule.scala | 27 ++++++---- scalalib/src/mill/scalalib/publish/settings.scala | 6 +-- 4 files changed, 89 insertions(+), 55 deletions(-) (limited to 'scalalib/src') 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, -- cgit v1.2.3