From 57501fca3b6c2c64d32744e6d534b9de3a6674f6 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sat, 13 Jan 2018 13:00:21 -0800 Subject: Migrate most classpath-related code onto `Loose.OSet` abstraction, to enforce deduplication --- build.sc | 32 ++-- core/src/main/scala/mill/define/Graph.scala | 3 +- core/src/main/scala/mill/discover/Discovered.scala | 2 +- core/src/main/scala/mill/eval/Evaluator.scala | 1 + .../main/scala/mill/main/ReplApplyHandler.scala | 2 +- core/src/main/scala/mill/main/RunScript.scala | 3 +- core/src/main/scala/mill/modules/Jvm.scala | 13 +- core/src/main/scala/mill/package.scala | 2 + core/src/main/scala/mill/util/MultiBiMap.scala | 2 +- core/src/main/scala/mill/util/OSet.scala | 192 +++++++++++---------- core/src/test/scala/mill/define/CacherTests.scala | 3 +- core/src/test/scala/mill/define/GraphTests.scala | 4 +- .../scala/mill/discover/ConsistencyTests.scala | 3 +- .../src/test/scala/mill/eval/EvaluationTests.scala | 3 +- core/src/test/scala/mill/eval/FailureTests.scala | 3 +- .../test/scala/mill/eval/JavaCompileJarTests.scala | 5 +- core/src/test/scala/mill/util/TestEvaluator.scala | 2 +- core/src/test/scala/mill/util/TestUtil.scala | 2 +- integration/src/test/resources/acyclic/build.sc | 9 +- .../src/test/resources/better-files/build.sc | 8 +- integration/src/test/resources/jawn/build.sc | 12 +- .../mill/integration/IntegrationTestSuite.scala | 2 +- .../src/main/scala/mill/scalajslib/Lib.scala | 8 +- .../main/scala/mill/scalajslib/ScalaJSModule.scala | 17 +- .../src/main/scala/mill/scalalib/GenIdea.scala | 3 +- scalalib/src/main/scala/mill/scalalib/Lib.scala | 27 +-- .../src/main/scala/mill/scalalib/MiscModule.scala | 15 +- scalalib/src/main/scala/mill/scalalib/Module.scala | 51 +++--- .../main/scala/mill/scalalib/PublishModule.scala | 2 +- .../src/main/scala/mill/scalalib/TestRunner.scala | 13 +- .../src/main/scala/mill/scalalib/publish/Ivy.scala | 4 +- .../src/main/scala/mill/scalalib/publish/Pom.scala | 4 +- .../scala/mill/scalalib/ResolveDepsTests.scala | 11 +- shared.sc | 2 +- 34 files changed, 250 insertions(+), 215 deletions(-) diff --git a/build.sc b/build.sc index 0fa484e9..d6a5448f 100755 --- a/build.sc +++ b/build.sc @@ -10,7 +10,7 @@ import mill.modules.Jvm.createAssembly object moduledefs extends SbtModule{ def scalaVersion = "2.12.4" - def ivyDeps = Seq( + def ivyDeps = OSet( Dep.Java("org.scala-lang", "scala-compiler", scalaVersion()), Dep("com.lihaoyi", "sourcecode", "0.1.4") ) @@ -19,9 +19,9 @@ object moduledefs extends SbtModule{ trait MillModule extends SbtModule{ outer => def scalaVersion = "2.12.4" - def compileIvyDeps = Seq(Dep("com.lihaoyi", "acyclic", "0.1.7")) + def compileIvyDeps = OSet(Dep("com.lihaoyi", "acyclic", "0.1.7")) def scalacOptions = Seq("-P:acyclic:force") - def scalacPluginIvyDeps = Seq(Dep("com.lihaoyi", "acyclic", "0.1.7")) + def scalacPluginIvyDeps = OSet(Dep("com.lihaoyi", "acyclic", "0.1.7")) def repositories = super.repositories ++ Seq( MavenRepository("https://oss.sonatype.org/content/repositories/releases") @@ -36,7 +36,7 @@ trait MillModule extends SbtModule{ outer => def projectDeps = if (this == core.test) Seq(core) else Seq(outer, core.test) - def ivyDeps = Seq(Dep("com.lihaoyi", "utest", "0.6.0")) + def ivyDeps = OSet(Dep("com.lihaoyi", "utest", "0.6.0")) def testFramework = "mill.UTestFramework" def scalacPluginClasspath = super.scalacPluginClasspath() ++ Seq(moduledefs.jar()) } @@ -45,11 +45,11 @@ trait MillModule extends SbtModule{ outer => object core extends MillModule { def projectDeps = Seq(moduledefs) - def compileIvyDeps = Seq( + def compileIvyDeps = OSet( Dep.Java("org.scala-lang", "scala-reflect", scalaVersion()) ) - def ivyDeps = Seq( + def ivyDeps = OSet( Dep("com.lihaoyi", "sourcecode", "0.1.4"), Dep("com.lihaoyi", "pprint", "0.5.3"), Dep.Point("com.lihaoyi", "ammonite", "1.0.3-21-05b5d32"), @@ -61,7 +61,7 @@ object core extends MillModule { def generatedSources = T { mkdir(T.ctx().dest) shared.generateCoreSources(T.ctx().dest) - Seq(PathRef(T.ctx().dest)) + OSet(PathRef(T.ctx().dest)) } val test = new Tests(implicitly) @@ -69,7 +69,7 @@ object core extends MillModule { def generatedSources = T { mkdir(T.ctx().dest) shared.generateCoreTestSources(T.ctx().dest) - Seq(PathRef(T.ctx().dest)) + OSet(PathRef(T.ctx().dest)) } } } @@ -83,9 +83,9 @@ class BridgeModule(crossVersion: String) extends PublishModule { def scalaVersion = crossVersion def allSources = T{ - Seq(PathRef(shared.downloadBridgeSource(T.ctx().dest, crossVersion))) + OSet(PathRef(shared.downloadBridgeSource(T.ctx().dest, crossVersion))) } - def ivyDeps = Seq( + def ivyDeps = OSet( Dep.Java("org.scala-lang", "scala-compiler", crossVersion), Dep.Java("org.scala-sbt", "compiler-interface", "1.0.5") ) @@ -125,7 +125,7 @@ class JsBridgeModule(scalajsBinary: String) extends MillModule{ case "0.6" => "0.6.21" case "1.0" => "1.0.0-M2" } - def ivyDeps = Seq( + def ivyDeps = OSet( Dep("org.scala-js", "scalajs-tools", scalajsVersion) ) } @@ -134,8 +134,8 @@ object scalajslib extends MillModule { def projectDeps = Seq(scalalib) - def bridgeClasspath(runDepClasspath: Seq[PathRef], classes: PathRef) = - (runDepClasspath :+ classes).map(_.path).mkString(File.pathSeparator) + def bridgeClasspath(runDepClasspath: OSet[PathRef], classes: PathRef) = + (runDepClasspath ++ OSet(classes)).map(_.path).mkString(File.pathSeparator) def testArgs = T{ val mapping = Map( "MILL_SCALAJS_BRIDGE_0_6" -> bridgeClasspath(jsbridges("0.6").runDepClasspath(), jsbridges("0.6").compile().classes), @@ -171,7 +171,7 @@ def publishBridges(credentials: String, gpgPassphrase: String) = T.command { mill.define.Task.traverse(bridges.items)(_._2.publish(credentials, gpgPassphrase)) } -def assemblyBase(classpath: Seq[Path], extraArgs: String) +def assemblyBase(classpath: OSet[Path], extraArgs: String) (implicit ctx: mill.util.Ctx.DestCtx) = { createAssembly( classpath, @@ -182,11 +182,11 @@ def assemblyBase(classpath: Seq[Path], extraArgs: String) } def devAssembly = T{ - assemblyBase(assemblyClasspath().flatten.map(_.path), (scalalib.testArgs() ++ scalajslib.testArgs()).mkString(" ")) + assemblyBase(OSet.from(assemblyClasspath().flatten.map(_.path)), (scalalib.testArgs() ++ scalajslib.testArgs()).mkString(" ")) } def releaseAssembly = T{ - assemblyBase(assemblyClasspath().flatten.map(_.path), "") + assemblyBase(OSet.from(assemblyClasspath().flatten.map(_.path)), "") } def idea() = T.command{ mill.scalalib.GenIdea() } \ No newline at end of file diff --git a/core/src/main/scala/mill/define/Graph.scala b/core/src/main/scala/mill/define/Graph.scala index e7844691..68fb65ed 100644 --- a/core/src/main/scala/mill/define/Graph.scala +++ b/core/src/main/scala/mill/define/Graph.scala @@ -1,7 +1,8 @@ package mill.define import mill.eval.Tarjans -import mill.util.{MultiBiMap, OSet} +import mill.util.MultiBiMap +import mill.util.Strict.OSet object Graph { class TopoSorted private[Graph](val values: OSet[Task[_]]) diff --git a/core/src/main/scala/mill/discover/Discovered.scala b/core/src/main/scala/mill/discover/Discovered.scala index c5ca4843..b7ec2140 100644 --- a/core/src/main/scala/mill/discover/Discovered.scala +++ b/core/src/main/scala/mill/discover/Discovered.scala @@ -5,7 +5,7 @@ import ammonite.main.Router import ammonite.main.Router.EntryPoint import mill.discover.Mirror.TargetPoint import mill.util.Ctx.Loader -import mill.util.OSet +import mill.util.Strict.OSet import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context diff --git a/core/src/main/scala/mill/eval/Evaluator.scala b/core/src/main/scala/mill/eval/Evaluator.scala index efb10d36..2afaec6e 100644 --- a/core/src/main/scala/mill/eval/Evaluator.scala +++ b/core/src/main/scala/mill/eval/Evaluator.scala @@ -9,6 +9,7 @@ import mill.discover.{Discovered, Mirror} import mill.define.Segment import mill.util import mill.util._ +import mill.util.Strict.OSet import scala.collection.mutable import scala.util.control.NonFatal diff --git a/core/src/main/scala/mill/main/ReplApplyHandler.scala b/core/src/main/scala/mill/main/ReplApplyHandler.scala index d4236487..b83453ee 100644 --- a/core/src/main/scala/mill/main/ReplApplyHandler.scala +++ b/core/src/main/scala/mill/main/ReplApplyHandler.scala @@ -5,7 +5,7 @@ import mill.define.Applicative.ApplyHandler import mill.define._ import mill.discover.{Discovered, Mirror} import mill.eval.{Evaluator, Result} -import mill.util.OSet +import mill.util.Strict.OSet import scala.collection.mutable object ReplApplyHandler{ diff --git a/core/src/main/scala/mill/main/RunScript.scala b/core/src/main/scala/mill/main/RunScript.scala index b8793b40..9f73fbc8 100644 --- a/core/src/main/scala/mill/main/RunScript.scala +++ b/core/src/main/scala/mill/main/RunScript.scala @@ -11,7 +11,8 @@ import mill.define.Task import mill.define.Segment import mill.discover.Discovered import mill.eval.{Evaluator, Result} -import mill.util.{EitherOps, Logger, OSet} +import mill.util.{EitherOps, Logger} +import mill.util.Strict.OSet import upickle.Js /** diff --git a/core/src/main/scala/mill/modules/Jvm.scala b/core/src/main/scala/mill/modules/Jvm.scala index e6806923..6e3fe45f 100644 --- a/core/src/main/scala/mill/modules/Jvm.scala +++ b/core/src/main/scala/mill/modules/Jvm.scala @@ -9,14 +9,15 @@ import ammonite.ops._ import mill.define.Task import mill.eval.PathRef import mill.util.Ctx +import mill.util.Loose.OSet import scala.annotation.tailrec import scala.collection.mutable object Jvm { - def gatherClassloaderJars(): Seq[Path] = { - val allJars = collection.mutable.Buffer.empty[Path] + def gatherClassloaderJars(): OSet[Path] = { + val allJars = new OSet.Mutable[Path]() var currentClassloader = Thread.currentThread().getContextClassLoader while(currentClassloader != null){ currentClassloader match{ @@ -29,14 +30,14 @@ object Jvm { } def interactiveSubprocess(mainClass: String, - classPath: Seq[Path], + classPath: OSet[Path], options: Seq[String] = Seq.empty): Unit = { import ammonite.ops.ImplicitWd._ %("java", "-cp", classPath.mkString(":"), mainClass, options) } def subprocess(mainClass: String, - classPath: Seq[Path], + classPath: OSet[Path], jvmOptions: Seq[String] = Seq.empty, options: Seq[String] = Seq.empty, workingDir: Path = null) @@ -100,7 +101,7 @@ object Jvm { m } - def createJar(inputPaths: Seq[Path], mainClass: Option[String] = None) + def createJar(inputPaths: OSet[Path], mainClass: Option[String] = None) (implicit ctx: Ctx.DestCtx): PathRef = { val outputPath = ctx.dest rm(outputPath) @@ -134,7 +135,7 @@ object Jvm { PathRef(outputPath) } - def createAssembly(inputPaths: Seq[Path], + def createAssembly(inputPaths: OSet[Path], mainClass: Option[String] = None, prependShellScript: String = "") (implicit ctx: Ctx.DestCtx): PathRef = { diff --git a/core/src/main/scala/mill/package.scala b/core/src/main/scala/mill/package.scala index 3463b63f..0b4f4873 100644 --- a/core/src/main/scala/mill/package.scala +++ b/core/src/main/scala/mill/package.scala @@ -8,4 +8,6 @@ package object mill extends JsonFormatters{ type Module = define.Module val Module = define.Module type Cross[T] = define.Cross[T] + type OSet[T] = util.Loose.OSet[T] + val OSet = util.Loose.OSet } diff --git a/core/src/main/scala/mill/util/MultiBiMap.scala b/core/src/main/scala/mill/util/MultiBiMap.scala index ef5359bc..abbaa752 100644 --- a/core/src/main/scala/mill/util/MultiBiMap.scala +++ b/core/src/main/scala/mill/util/MultiBiMap.scala @@ -1,7 +1,7 @@ package mill.util import scala.collection.mutable - +import Strict.OSet /** * A map from keys to collections of values: you can assign multiple values * to any particular key. Also allows lookups in both directions: what values diff --git a/core/src/main/scala/mill/util/OSet.scala b/core/src/main/scala/mill/util/OSet.scala index 52b47cde..a4fcc406 100644 --- a/core/src/main/scala/mill/util/OSet.scala +++ b/core/src/main/scala/mill/util/OSet.scala @@ -3,108 +3,114 @@ package mill.util import scala.collection.mutable - -/** - * A collection with enforced uniqueness, fast contains and deterministic - * ordering. Raises an exception if a duplicate is found; call - * `toSeq.distinct` if you explicitly want to make it swallow duplicates - */ -trait OSet[V] extends TraversableOnce[V]{ - def contains(v: V): Boolean - def items: Iterator[V] - def indexed: IndexedSeq[V] - def flatMap[T](f: V => TraversableOnce[T]): OSet[T] - def map[T](f: V => T): OSet[T] - def filter(f: V => Boolean): OSet[V] - def withFilter(f: V => Boolean): OSet[V] - def collect[T](f: PartialFunction[V, T]): OSet[T] - def zipWithIndex: OSet[(V, Int)] - def reverse: OSet[V] - def zip[T](other: OSet[T]): OSet[(V, T)] -} - -object OSet{ - implicit def jsonFormat[T: upickle.default.ReadWriter]: upickle.default.ReadWriter[OSet[T]] = - upickle.default.ReadWriter[OSet[T]] ( - oset => upickle.default.writeJs(oset.toList), - {case json => OSet.from(upickle.default.readJs[Seq[T]](json))} - ) - def apply[V](items: V*) = from(items) - - def from[V](items: TraversableOnce[V]): OSet[V] = { - val set = new OSet.Mutable[V]() - items.foreach(set.append) - set +object Strict extends OSetWrapper(true) +object Loose extends OSetWrapper(false) +sealed class OSetWrapper(strictUniqueness: Boolean){ + /** + * A collection with enforced uniqueness, fast contains and deterministic + * ordering. Raises an exception if a duplicate is found; call + * `toSeq.distinct` if you explicitly want to make it swallow duplicates + */ + trait OSet[V] extends TraversableOnce[V]{ + def contains(v: V): Boolean + def items: Iterator[V] + def indexed: IndexedSeq[V] + def flatMap[T](f: V => TraversableOnce[T]): OSet[T] + def map[T](f: V => T): OSet[T] + def filter(f: V => Boolean): OSet[V] + def withFilter(f: V => Boolean): OSet[V] + def collect[T](f: PartialFunction[V, T]): OSet[T] + def zipWithIndex: OSet[(V, Int)] + def reverse: OSet[V] + def zip[T](other: OSet[T]): OSet[(V, T)] + def ++[T >: V](other: TraversableOnce[T]): OSet[T] } + object OSet{ + def empty[V]: OSet[V] = new OSet.Mutable[V] + implicit def jsonFormat[T: upickle.default.ReadWriter]: upickle.default.ReadWriter[OSet[T]] = + upickle.default.ReadWriter[OSet[T]] ( + oset => upickle.default.writeJs(oset.toList), + {case json => OSet.from(upickle.default.readJs[Seq[T]](json))} + ) + def apply[V](items: V*) = from(items) + + def from[V](items: TraversableOnce[V]): OSet[V] = { + val set = new OSet.Mutable[V]() + items.foreach(set.append) + set + } - class Mutable[V]() extends OSet[V]{ - private[this] val set0 = mutable.LinkedHashSet.empty[V] - def contains(v: V) = set0.contains(v) - def append(v: V) = if (!contains(v)){ - set0.add(v) + class Mutable[V]() extends OSet[V]{ - }else { - throw new Exception("Duplicated item inserted into OrderedSet: " + v) - } - def appendAll(vs: Seq[V]) = vs.foreach(append) - def items = set0.iterator - def indexed: IndexedSeq[V] = items.toIndexedSeq - def set: collection.Set[V] = set0 - - def map[T](f: V => T): OSet[T] = { - val output = new OSet.Mutable[T] - for(i <- items) output.append(f(i)) - output - } - def flatMap[T](f: V => TraversableOnce[T]): OSet[T] = { - val output = new OSet.Mutable[T] - for(i <- items) for(i0 <- f(i)) output.append(i0) - output - } - def filter(f: V => Boolean): OSet[V] = { - val output = new OSet.Mutable[V] - for(i <- items) if (f(i)) output.append(i) - output - } - def withFilter(f: V => Boolean): OSet[V] = filter(f) + private[this] val set0 = mutable.LinkedHashSet.empty[V] + def contains(v: V) = set0.contains(v) + def append(v: V) = if (!contains(v)){ + set0.add(v) - def collect[T](f: PartialFunction[V, T]) = this.filter(f.isDefinedAt).map(x => f(x)) + }else if (strictUniqueness){ + throw new Exception("Duplicated item inserted into OrderedSet: " + v) + } + def appendAll(vs: Seq[V]) = vs.foreach(append) + def items = set0.iterator + def indexed: IndexedSeq[V] = items.toIndexedSeq + def set: collection.Set[V] = set0 + + def map[T](f: V => T): OSet[T] = { + val output = new OSet.Mutable[T] + for(i <- items) output.append(f(i)) + output + } + def flatMap[T](f: V => TraversableOnce[T]): OSet[T] = { + val output = new OSet.Mutable[T] + for(i <- items) for(i0 <- f(i)) output.append(i0) + output + } + def filter(f: V => Boolean): OSet[V] = { + val output = new OSet.Mutable[V] + for(i <- items) if (f(i)) output.append(i) + output + } + def withFilter(f: V => Boolean): OSet[V] = filter(f) - def zipWithIndex = { - var i = 0 - this.map{ x => - i += 1 - (x, i-1) + def collect[T](f: PartialFunction[V, T]) = this.filter(f.isDefinedAt).map(x => f(x)) + + def zipWithIndex = { + var i = 0 + this.map{ x => + i += 1 + (x, i-1) + } } - } - def reverse = OSet.from(indexed.reverseIterator) - - def zip[T](other: OSet[T]) = OSet.from(items.zip(other.items)) - - // Members declared in scala.collection.GenTraversableOnce - def isTraversableAgain: Boolean = items.isTraversableAgain - def toIterator: Iterator[V] = items.toIterator - def toStream: Stream[V] = items.toStream - - // Members declared in scala.collection.TraversableOnce - def copyToArray[B >: V](xs: Array[B],start: Int,len: Int): Unit = items.copyToArray(xs, start, len) - def exists(p: V => Boolean): Boolean = items.exists(p) - def find(p: V => Boolean): Option[V] = items.find(p) - def forall(p: V => Boolean): Boolean = items.forall(p) - def foreach[U](f: V => U): Unit = items.foreach(f) - def hasDefiniteSize: Boolean = items.hasDefiniteSize - def isEmpty: Boolean = items.isEmpty - def seq: scala.collection.TraversableOnce[V] = items - def toTraversable: Traversable[V] = items.toTraversable - - override def hashCode() = items.hashCode() - override def equals(other: Any) = other match{ - case s: OSet[_] => items.sameElements(s.items) - case _ => super.equals(other) + def reverse = OSet.from(indexed.reverseIterator) + + def zip[T](other: OSet[T]) = OSet.from(items.zip(other.items)) + def ++[T >: V](other: TraversableOnce[T]) = OSet.from(items ++ other) + + // Members declared in scala.collection.GenTraversableOnce + def isTraversableAgain: Boolean = items.isTraversableAgain + def toIterator: Iterator[V] = items.toIterator + def toStream: Stream[V] = items.toStream + + // Members declared in scala.collection.TraversableOnce + def copyToArray[B >: V](xs: Array[B], start: Int,len: Int): Unit = items.copyToArray(xs, start, len) + def exists(p: V => Boolean): Boolean = items.exists(p) + def find(p: V => Boolean): Option[V] = items.find(p) + def forall(p: V => Boolean): Boolean = items.forall(p) + def foreach[U](f: V => U): Unit = items.foreach(f) + def hasDefiniteSize: Boolean = items.hasDefiniteSize + def isEmpty: Boolean = items.isEmpty + def seq: scala.collection.TraversableOnce[V] = items + def toTraversable: Traversable[V] = items.toTraversable + + override def hashCode() = items.map(_.hashCode()).sum + override def equals(other: Any) = other match{ + case s: OSet[_] => items.sameElements(s.items) + case _ => super.equals(other) + } + override def toString = items.mkString("OSet(", ", ", ")") } - override def toString = items.mkString("OSet(", ", ", ")") } } diff --git a/core/src/test/scala/mill/define/CacherTests.scala b/core/src/test/scala/mill/define/CacherTests.scala index faf274f2..4127a75b 100644 --- a/core/src/test/scala/mill/define/CacherTests.scala +++ b/core/src/test/scala/mill/define/CacherTests.scala @@ -2,7 +2,8 @@ package mill.define import mill.discover.Discovered import mill.eval.Evaluator -import mill.util.{DummyLogger, OSet, TestUtil} +import mill.util.{DummyLogger, TestUtil} +import mill.util.Strict.OSet import mill.T import mill.eval.Result.Success import utest._ diff --git a/core/src/test/scala/mill/define/GraphTests.scala b/core/src/test/scala/mill/define/GraphTests.scala index 718fd673..7241087a 100644 --- a/core/src/test/scala/mill/define/GraphTests.scala +++ b/core/src/test/scala/mill/define/GraphTests.scala @@ -4,9 +4,9 @@ package mill.define import mill.discover.Discovered import Discovered.mapping import mill.eval.Evaluator -import mill.util.{OSet, TestGraphs, TestUtil} +import mill.util.{TestGraphs, TestUtil} import utest._ - +import mill.util.Strict.OSet object GraphTests extends TestSuite{ val tests = Tests{ diff --git a/core/src/test/scala/mill/discover/ConsistencyTests.scala b/core/src/test/scala/mill/discover/ConsistencyTests.scala index 190b2cee..4a9ae843 100644 --- a/core/src/test/scala/mill/discover/ConsistencyTests.scala +++ b/core/src/test/scala/mill/discover/ConsistencyTests.scala @@ -3,7 +3,8 @@ package mill.discover import mill.define.Segment.Label import mill.define.Segments -import mill.util.{OSet, TestGraphs} +import mill.util.{TestGraphs} +import mill.util.Strict.OSet import utest._ object ConsistencyTests extends TestSuite{ diff --git a/core/src/test/scala/mill/eval/EvaluationTests.scala b/core/src/test/scala/mill/eval/EvaluationTests.scala index 54e184b5..2b9dd102 100644 --- a/core/src/test/scala/mill/eval/EvaluationTests.scala +++ b/core/src/test/scala/mill/eval/EvaluationTests.scala @@ -6,7 +6,8 @@ import mill.define.{Graph, Target, Task} import mill.{Module, T} import mill.discover.Discovered import mill.discover.Discovered.mapping -import mill.util.{DummyLogger, OSet, TestGraphs, TestUtil} +import mill.util.{DummyLogger, TestGraphs, TestUtil} +import mill.util.Strict.OSet import utest._ import utest.framework.TestPath diff --git a/core/src/test/scala/mill/eval/FailureTests.scala b/core/src/test/scala/mill/eval/FailureTests.scala index c2057cd1..ef206740 100644 --- a/core/src/test/scala/mill/eval/FailureTests.scala +++ b/core/src/test/scala/mill/eval/FailureTests.scala @@ -3,7 +3,8 @@ package mill.eval import mill.define.Target import mill.discover.Discovered import mill.discover.Discovered.mapping -import mill.util.{DummyLogger, OSet} +import mill.util.DummyLogger +import mill.util.Strict.OSet import utest._ import utest.framework.TestPath diff --git a/core/src/test/scala/mill/eval/JavaCompileJarTests.scala b/core/src/test/scala/mill/eval/JavaCompileJarTests.scala index c8320fcd..8105f2fa 100644 --- a/core/src/test/scala/mill/eval/JavaCompileJarTests.scala +++ b/core/src/test/scala/mill/eval/JavaCompileJarTests.scala @@ -7,7 +7,8 @@ import mill.discover.Discovered import mill.modules.Jvm import mill.util.Ctx.DestCtx import mill.{Module, T} -import mill.util.{DummyLogger, OSet, TestUtil} +import mill.util.{DummyLogger, Loose, TestUtil} +import mill.util.Strict.OSet import utest._ import mill._ @@ -40,7 +41,7 @@ object JavaCompileJarTests extends TestSuite{ def resourceRoot = T.source{ resourceRootPath } def allSources = T{ ls.rec(sourceRoot().path).map(PathRef(_)) } def classFiles = T{ compileAll(allSources()) } - def jar = T{ Jvm.createJar(Seq(resourceRoot().path, classFiles().path)) } + def jar = T{ Jvm.createJar(Loose.OSet(resourceRoot().path, classFiles().path)) } def run(mainClsName: String) = T.command{ %%('java, "-cp", classFiles().path, mainClsName) diff --git a/core/src/test/scala/mill/util/TestEvaluator.scala b/core/src/test/scala/mill/util/TestEvaluator.scala index 646ca418..3f6086ba 100644 --- a/core/src/test/scala/mill/util/TestEvaluator.scala +++ b/core/src/test/scala/mill/util/TestEvaluator.scala @@ -4,7 +4,7 @@ import ammonite.ops.Path import mill.define.{Input, Target, Task} import mill.discover.{Discovered, Mirror} import mill.eval.{Evaluator, Result} - +import mill.util.Strict.OSet class TestEvaluator(mapping: Discovered.Mapping[_], workspacePath: Path, basePath: Path){ diff --git a/core/src/test/scala/mill/util/TestUtil.scala b/core/src/test/scala/mill/util/TestUtil.scala index ae985665..3cc945db 100644 --- a/core/src/test/scala/mill/util/TestUtil.scala +++ b/core/src/test/scala/mill/util/TestUtil.scala @@ -4,7 +4,7 @@ import ammonite.main.Router.Overrides import mill.define._ import mill.eval.Result import utest.assert - +import mill.util.Strict.OSet import scala.collection.mutable object TestUtil { diff --git a/integration/src/test/resources/acyclic/build.sc b/integration/src/test/resources/acyclic/build.sc index 66d64501..094893f5 100644 --- a/integration/src/test/resources/acyclic/build.sc +++ b/integration/src/test/resources/acyclic/build.sc @@ -1,9 +1,9 @@ import mill.Cross -import mill.scalalib.{SbtModule, PublishModule, Dep} +import mill.scalalib.{SbtModule, PublishModule, Dep, CrossSbtModule} import mill.scalalib.publish.{PomSettings, License, Developer, SCM} object acyclic extends Cross[AcyclicModule]("2.10.6", "2.11.8", "2.12.3", "2.12.4") -class AcyclicModule(crossVersion: String) extends SbtModule with PublishModule { +class AcyclicModule(val crossScalaVersion: String) extends CrossSbtModule with PublishModule { def basePath = super.basePath / ammonite.ops.up def artifactName = "acyclic" def publishVersion = "0.1.7" @@ -24,13 +24,12 @@ class AcyclicModule(crossVersion: String) extends SbtModule with PublishModule { ) ) - def scalaVersion = crossVersion - def ivyDeps = Seq( + def ivyDeps = OSet( Dep.Java("org.scala-lang", "scala-compiler", scalaVersion()) ) object test extends Tests{ def forkWorkingDir = ammonite.ops.pwd / 'target / 'workspace / 'acyclic - def ivyDeps = Seq( + def ivyDeps = OSet( Dep("com.lihaoyi", "utest", "0.6.0") ) def testFramework = "utest.runner.Framework" diff --git a/integration/src/test/resources/better-files/build.sc b/integration/src/test/resources/better-files/build.sc index cd6cac04..fe11f1b8 100644 --- a/integration/src/test/resources/better-files/build.sc +++ b/integration/src/test/resources/better-files/build.sc @@ -54,7 +54,7 @@ trait BetterFilesModule extends SbtModule{ def projectDeps = if (this == core.test) super.projectDeps else super.projectDeps ++ Seq(core.test) - def ivyDeps = Seq(Dep("org.scalatest", "scalatest", "3.0.4")) + def ivyDeps = OSet(Dep("org.scalatest", "scalatest", "3.0.4")) def testFramework = "org.scalatest.tools.Framework" } } @@ -63,17 +63,17 @@ object core extends BetterFilesModule object akka extends BetterFilesModule{ def projectDeps = Seq(core) - def ivyDeps = Seq(Dep("com.typesafe.akka", "akka-actor", "2.5.6")) + def ivyDeps = OSet(Dep("com.typesafe.akka", "akka-actor", "2.5.6")) } object shapeless extends BetterFilesModule{ def projectDeps = Seq(core) - def ivyDeps = Seq(Dep("com.chuusai", "shapeless", "2.3.2")) + def ivyDeps = OSet(Dep("com.chuusai", "shapeless", "2.3.2")) } object benchmarks extends BetterFilesModule{ def projectDeps = Seq(core) - def ivyDeps = Seq( + def ivyDeps = OSet( Dep.Java("commons-io", "commons-io", "2.5") // "fastjavaio" % "fastjavaio" % "1.0" from "https://github.com/williamfiset/FastJavaIO/releases/download/v1.0/fastjavaio.jar" ) diff --git a/integration/src/test/resources/jawn/build.sc b/integration/src/test/resources/jawn/build.sc index 8b830f70..a90d93b5 100644 --- a/integration/src/test/resources/jawn/build.sc +++ b/integration/src/test/resources/jawn/build.sc @@ -4,7 +4,7 @@ import mill.scalalib.{Dep, TestModule, Module} object jawn extends Cross[JawnModule]("2.10.6", "2.11.11", "2.12.3") class JawnModule(crossVersion: String) extends mill.Module{ - override def basePath = super.basePath / ammonite.ops.up + override def basePath = super.basePath / ammonite.ops.up / ammonite.ops.up trait JawnModule extends scalalib.SbtModule{ def scalaVersion = crossVersion @@ -16,7 +16,7 @@ class JawnModule(crossVersion: String) extends mill.Module{ def testProjectDeps: Seq[TestModule] = Nil object test extends Tests{ def projectDeps = super.projectDeps ++ testProjectDeps - def ivyDeps = Seq( + def ivyDeps = OSet( Dep("org.scalatest", "scalatest", "3.0.3"), Dep("org.scalacheck", "scalacheck", "1.13.5") ) @@ -35,7 +35,7 @@ class JawnModule(crossVersion: String) extends mill.Module{ } class Support(ivyDeps0: Dep*)(implicit ctx: mill.Module.Ctx) extends JawnModule{ def projectDeps = Seq[Module](parser) - def ivyDeps = ivyDeps0 + def ivyDeps = OSet.from(ivyDeps0) } object support extends mill.Module{ object argonaut extends Support(Dep("io.argonaut", "argonaut", "6.2")) @@ -44,9 +44,9 @@ class JawnModule(crossVersion: String) extends mill.Module{ object play extends Support(){ def ivyDeps = mill.T{ scalaBinaryVersion() match{ - case "2.10" => Seq(Dep("com.typesafe.play", "play-json", "2.4.11")) - case "2.11" => Seq(Dep("com.typesafe.play", "play-json", "2.5.15")) - case _ => Seq(Dep("com.typesafe.play", "play-json", "2.6.0")) + case "2.10" => OSet(Dep("com.typesafe.play", "play-json", "2.4.11")) + case "2.11" => OSet(Dep("com.typesafe.play", "play-json", "2.5.15")) + case _ => OSet(Dep("com.typesafe.play", "play-json", "2.6.0")) } } } diff --git a/integration/src/test/scala/mill/integration/IntegrationTestSuite.scala b/integration/src/test/scala/mill/integration/IntegrationTestSuite.scala index ba4415fa..82f4de72 100644 --- a/integration/src/test/scala/mill/integration/IntegrationTestSuite.scala +++ b/integration/src/test/scala/mill/integration/IntegrationTestSuite.scala @@ -8,7 +8,7 @@ import utest._ abstract class IntegrationTestSuite(repoKey: String, workspaceSlug: String) extends TestSuite{ val workspacePath = pwd / 'target / 'workspace / workspaceSlug val buildFilePath = pwd / 'integration / 'src / 'test / 'resources / workspaceSlug - val stdOutErr = new PrintStream(new ByteArrayOutputStream()) + val stdOutErr = System.out//new PrintStream(new ByteArrayOutputStream()) val stdIn = new ByteArrayInputStream(Array()) val runner = new mill.main.MainRunner( ammonite.main.Cli.Config(wd = workspacePath), false, diff --git a/scalajslib/src/main/scala/mill/scalajslib/Lib.scala b/scalajslib/src/main/scala/mill/scalajslib/Lib.scala index 3de37962..744bb262 100644 --- a/scalajslib/src/main/scala/mill/scalajslib/Lib.scala +++ b/scalajslib/src/main/scala/mill/scalajslib/Lib.scala @@ -7,7 +7,7 @@ import java.net.URLClassLoader import ammonite.ops.{Path, mkdir, rm, _} import mill.eval.PathRef import mill.scalalib.Dep -import mill.util.Ctx +import mill.util.{Ctx, Loose} import scala.collection.breakOut import scala.language.reflectiveCalls @@ -21,7 +21,7 @@ object Lib { def scalaJSLinkerIvyDep(scalaJSVersion: String): Dep = Dep("com.lihaoyi", s"mill-jsbridge_${scalaJSVersion.replace('.', '_')}", "0.1-SNAPSHOT") - def scalaJSLinkerBridge(classPath: Seq[Path]): ScalaJSLinkerBridge = { + def scalaJSLinkerBridge(classPath: Loose.OSet[Path]): ScalaJSLinkerBridge = { val classloaderSig = classPath.map(p => p.toString().hashCode + p.mtime.toMillis).sum LinkerBridge.scalaInstanceCache match { case Some((`classloaderSig`, linker)) => linker @@ -44,7 +44,7 @@ object Lib { def link(main: Option[String], inputPaths: Seq[Path], - libraries: Seq[Path], + libraries: Loose.OSet[Path], linker: ScalaJSLinkerBridge, mode: OptimizeMode) (implicit ctx: Ctx.DestCtx): PathRef = { @@ -53,7 +53,7 @@ object Lib { if (inputPaths.nonEmpty) { mkdir(outputPath / up) val inputFiles: Vector[File] = inputPaths.map(ls).flatMap(_.filter(_.ext == "sjsir")).map(_.toIO)(breakOut) - val inputLibraries: Vector[File] = libraries.filter(_.ext == "jar").map(_.toIO)(breakOut) + val inputLibraries: Vector[File] = libraries.filter(_.ext == "jar").map(_.toIO).toVector linker.link(inputFiles, inputLibraries, outputPath.toIO, main, mode) } PathRef(outputPath) diff --git a/scalajslib/src/main/scala/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/main/scala/mill/scalajslib/ScalaJSModule.scala index ed0a2c85..03c4e216 100644 --- a/scalajslib/src/main/scala/mill/scalajslib/ScalaJSModule.scala +++ b/scalajslib/src/main/scala/mill/scalajslib/ScalaJSModule.scala @@ -7,7 +7,8 @@ import ammonite.ops.Path import mill.eval.Result.Success import mill.scalajslib.Lib._ import mill.scalalib.Lib.resolveDependencies -import mill.scalalib.{Dep, PublishModule, Module, TestModule} +import mill.scalalib.{Dep, Module, PublishModule, TestModule} +import mill.util.Loose trait ScalaJSModule extends scalalib.Module { outer => @@ -26,10 +27,16 @@ trait ScalaJSModule extends scalalib.Module { outer => def scalaJSBridgeVersion = T{ scalaJSVersion().split('.').dropRight(1).mkString(".") } - def scalaJSLinkerClasspath: T[Seq[PathRef]] = T{ + def scalaJSLinkerClasspath: T[Loose.OSet[PathRef]] = T{ val jsBridgeKey = "MILL_SCALAJS_BRIDGE_" + scalaJSBridgeVersion().replace('.', '_') val jsBridgePath = sys.props(jsBridgeKey) - if (jsBridgePath != null) Success(jsBridgePath.split(File.pathSeparator).map(f => PathRef(Path(f), quick = true)).toVector) + if (jsBridgePath != null) { + Success( + Loose.OSet.from( + jsBridgePath.split(File.pathSeparator).map(f => PathRef(Path(f), quick = true)) + ) + ) + } else { val dep = scalaJSLinkerIvyDep(scalaJSBridgeVersion()) resolveDependencies( @@ -51,9 +58,9 @@ trait ScalaJSModule extends scalalib.Module { outer => link(mainClass(), Seq(compile().classes.path), compileDepClasspath().map(_.path), linker, FullOpt) } - override def scalacPluginIvyDeps = T{ Seq(Dep.Point("org.scala-js", "scalajs-compiler", scalaJSVersion())) } + override def scalacPluginIvyDeps = T{ Loose.OSet(Dep.Point("org.scala-js", "scalajs-compiler", scalaJSVersion())) } - override def ivyDeps = T{ Seq(Dep("org.scala-js", "scalajs-library", scalaJSVersion())) } + override def ivyDeps = T{ Loose.OSet(Dep("org.scala-js", "scalajs-library", scalaJSVersion())) } // publish artifact with name "mill_sjs0.6.4_2.12" instead of "mill_sjs0.6_2.12" def crossFullScalaJSVersion: T[Boolean] = false diff --git a/scalalib/src/main/scala/mill/scalalib/GenIdea.scala b/scalalib/src/main/scala/mill/scalalib/GenIdea.scala index 24daef2c..cd664495 100644 --- a/scalalib/src/main/scala/mill/scalalib/GenIdea.scala +++ b/scalalib/src/main/scala/mill/scalalib/GenIdea.scala @@ -5,7 +5,8 @@ import mill.define.{Segment, Segments, Target} import mill.discover.{Discovered, Mirror} import mill.eval.{Evaluator, PathRef} import mill.util.Ctx.{LoaderCtx, LogCtx} -import mill.util.{OSet, PrintLogger} +import mill.util.{PrintLogger} +import mill.util.Strict.OSet object GenIdea { diff --git a/scalalib/src/main/scala/mill/scalalib/Lib.scala b/scalalib/src/main/scala/mill/scalalib/Lib.scala index 098da786..54b1a817 100644 --- a/scalalib/src/main/scala/mill/scalalib/Lib.scala +++ b/scalalib/src/main/scala/mill/scalalib/Lib.scala @@ -9,7 +9,8 @@ import ammonite.ops._ import coursier.{Cache, Fetch, MavenRepository, Repository, Resolution, Module => CoursierModule} import mill.define.Worker import mill.eval.{PathRef, Result} -import mill.util.Ctx +import mill.util.{Ctx} +import mill.util.Loose.OSet import sbt.internal.inc._ import sbt.internal.util.{ConsoleOut, MainAppender} import sbt.util.LogExchange @@ -38,7 +39,7 @@ object Lib{ Locate.definesClass(classpathEntry) } - def grepJar(classPath: Seq[Path], s: String) = { + def grepJar(classPath: OSet[Path], s: String) = { classPath .find(_.toString.endsWith(s)) .getOrElse(throw new Exception("Cannot find " + s)) @@ -47,13 +48,13 @@ object Lib{ def compileScala(zincWorker: ZincWorker, scalaVersion: String, - sources: Seq[Path], - compileClasspath: Seq[Path], - compilerClasspath: Seq[Path], - pluginClasspath: Seq[Path], + sources: OSet[Path], + compileClasspath: OSet[Path], + compilerClasspath: OSet[Path], + pluginClasspath: OSet[Path], compilerBridge: Path, scalacOptions: Seq[String], - scalacPluginClasspath: Seq[Path], + scalacPluginClasspath: OSet[Path], javacOptions: Seq[String], upstreamCompileOutput: Seq[CompilationResult]) (implicit ctx: Ctx): CompilationResult = { @@ -171,8 +172,8 @@ object Lib{ def resolveDependencies(repositories: Seq[Repository], scalaVersion: String, scalaBinaryVersion: String, - deps: Seq[Dep], - sources: Boolean = false): Result[Seq[PathRef]] = { + deps: TraversableOnce[Dep], + sources: Boolean = false): Result[OSet[PathRef]] = { val flattened = deps.map{ case Dep.Java(dep) => dep case Dep.Scala(dep) => @@ -206,14 +207,16 @@ object Lib{ .unsafePerformSync .flatMap(_.toOption) - localArtifacts.map(p => PathRef(Path(p), quick = true)).filter(_.path.ext == "jar") + OSet.from( + localArtifacts.map(p => PathRef(Path(p), quick = true)).filter(_.path.ext == "jar") + ) } } - def scalaCompilerIvyDeps(scalaVersion: String) = Seq( + def scalaCompilerIvyDeps(scalaVersion: String) = OSet[Dep]( Dep.Java("org.scala-lang", "scala-compiler", scalaVersion), Dep.Java("org.scala-lang", "scala-reflect", scalaVersion) ) - def scalaRuntimeIvyDeps(scalaVersion: String) = Seq[Dep]( + def scalaRuntimeIvyDeps(scalaVersion: String) = OSet[Dep]( Dep.Java("org.scala-lang", "scala-library", scalaVersion) ) def compilerBridgeIvyDep(scalaVersion: String) = diff --git a/scalalib/src/main/scala/mill/scalalib/MiscModule.scala b/scalalib/src/main/scala/mill/scalalib/MiscModule.scala index 60d9d1ce..26609bcd 100644 --- a/scalalib/src/main/scala/mill/scalalib/MiscModule.scala +++ b/scalalib/src/main/scala/mill/scalalib/MiscModule.scala @@ -1,18 +1,19 @@ package mill package scalalib +import mill.define.Cross.Resolver import mill.define.{Cross, Task} import mill.eval.{PathRef, Result} -import mill.define.Cross.Resolver +import mill.util.Loose.OSet trait SbtModule extends Module { outer => - override def sources = T.input{ Seq(PathRef(basePath / 'src / 'main / 'scala)) } - override def resources = T.input{ Seq(PathRef(basePath / 'src / 'main / 'resources)) } + override def sources = T.input{ OSet(PathRef(basePath / 'src / 'main / 'scala)) } + override def resources = T.input{ OSet(PathRef(basePath / 'src / 'main / 'resources)) } trait Tests extends super.Tests { override def basePath = outer.basePath - override def sources = T.input{ Seq(PathRef(basePath / 'src / 'test / 'scala)) } - override def resources = T.input{ Seq(PathRef(basePath / 'src / 'test / 'resources)) } + override def sources = T.input{ OSet(PathRef(basePath / 'src / 'test / 'scala)) } + override def resources = T.input{ OSet(PathRef(basePath / 'src / 'test / 'resources)) } } } @@ -45,7 +46,7 @@ trait CrossSbtModule extends SbtModule { outer => } } - override def resources = T.input{ Seq(PathRef(basePath / 'src / 'main / 'resources)) } + override def resources = T.input{ OSet(PathRef(basePath / 'src / 'main / 'resources)) } trait Tests extends super.Tests { override def basePath = outer.basePath override def sources = T.input{ @@ -54,7 +55,7 @@ trait CrossSbtModule extends SbtModule { outer => s => PathRef{ basePath / 'src / 'test / s"scala-$s" } } } - override def resources = T.input{ Seq(PathRef(basePath / 'src / 'test / 'resources)) } + override def resources = T.input{ OSet(PathRef(basePath / 'src / 'test / 'resources)) } } } diff --git a/scalalib/src/main/scala/mill/scalalib/Module.scala b/scalalib/src/main/scala/mill/scalalib/Module.scala index d0041fb5..2a7d6edb 100644 --- a/scalalib/src/main/scala/mill/scalalib/Module.scala +++ b/scalalib/src/main/scala/mill/scalalib/Module.scala @@ -10,6 +10,7 @@ import mill.modules.Jvm import mill.modules.Jvm.{createAssembly, createJar, interactiveSubprocess, subprocess} import Lib._ import mill.define.Cross.Resolver +import mill.util.Loose.OSet import sbt.testing.Status /** @@ -25,10 +26,10 @@ trait Module extends mill.Module with TaskModule { outer => def mainClass: T[Option[String]] = None def scalaBinaryVersion = T{ scalaVersion().split('.').dropRight(1).mkString(".") } - def ivyDeps = T{ Seq[Dep]() } - def compileIvyDeps = T{ Seq[Dep]() } - def scalacPluginIvyDeps = T{ Seq[Dep]() } - def runIvyDeps = T{ Seq[Dep]() } + def ivyDeps = T{ OSet.empty[Dep] } + def compileIvyDeps = T{ OSet.empty[Dep] } + def scalacPluginIvyDeps = T{ OSet.empty[Dep] } + def runIvyDeps = T{ OSet.empty[Dep] } def scalacOptions = T{ Seq.empty[String] } def javacOptions = T{ Seq.empty[String] } @@ -39,7 +40,7 @@ trait Module extends mill.Module with TaskModule { outer => ) def projectDeps = Seq.empty[Module] - def depClasspath = T{ Seq.empty[PathRef] } + def depClasspath = T{ OSet.empty[PathRef] } def upstreamRunClasspath = T{ @@ -57,7 +58,7 @@ trait Module extends mill.Module with TaskModule { outer => Task.traverse(projectDeps)(_.compileDepClasspath)().flatten } - def resolveDeps(deps: Task[Seq[Dep]], sources: Boolean = false) = T.task{ + def resolveDeps(deps: Task[OSet[Dep]], sources: Boolean = false) = T.task{ resolveDependencies( repositories, scalaVersion(), @@ -67,15 +68,15 @@ trait Module extends mill.Module with TaskModule { outer => ) } - def externalCompileDepClasspath: T[Seq[PathRef]] = T{ - Task.traverse(projectDeps)(_.externalCompileDepClasspath)().flatten ++ + def externalCompileDepClasspath: T[OSet[PathRef]] = T{ + OSet.from(Task.traverse(projectDeps)(_.externalCompileDepClasspath)().flatten) ++ resolveDeps( T.task{ivyDeps() ++ compileIvyDeps() ++ scalaCompilerIvyDeps(scalaVersion())} )() } - def externalCompileDepSources: T[Seq[PathRef]] = T{ - Task.traverse(projectDeps)(_.externalCompileDepSources)().flatten ++ + def externalCompileDepSources: T[OSet[PathRef]] = T{ + OSet.from(Task.traverse(projectDeps)(_.externalCompileDepSources)().flatten) ++ resolveDeps( T.task{ivyDeps() ++ compileIvyDeps() ++ scalaCompilerIvyDeps(scalaVersion())}, sources = true @@ -86,7 +87,7 @@ trait Module extends mill.Module with TaskModule { outer => * Things that need to be on the classpath in order for this code to compile; * might be less than the runtime classpath */ - def compileDepClasspath: T[Seq[PathRef]] = T{ + def compileDepClasspath: T[OSet[PathRef]] = T{ upstreamCompileClasspath() ++ depClasspath() } @@ -108,7 +109,7 @@ trait Module extends mill.Module with TaskModule { outer => ) classpath match { case Result.Success(resolved) => - resolved.filterNot(_.path.ext == "pom") match { + resolved.filter(_.path.ext != "pom").toSeq match { case Seq(single) => PathRef(single.path, quick = true) case Seq() => throw new Exception(dep + " resolution failed") // TODO: find out, is it possible? case _ => throw new Exception(dep + " resolution resulted in more than one file") @@ -118,7 +119,7 @@ trait Module extends mill.Module with TaskModule { outer => } } - def scalacPluginClasspath: T[Seq[PathRef]] = + def scalacPluginClasspath: T[OSet[PathRef]] = resolveDeps( T.task{scalacPluginIvyDeps()} )() @@ -126,7 +127,7 @@ trait Module extends mill.Module with TaskModule { outer => /** * Classpath of the Scala Compiler & any compiler plugins */ - def scalaCompilerClasspath: T[Seq[PathRef]] = T{ + def scalaCompilerClasspath: T[OSet[PathRef]] = T{ resolveDeps( T.task{scalaCompilerIvyDeps(scalaVersion()) ++ scalaRuntimeIvyDeps(scalaVersion())} )() @@ -135,19 +136,19 @@ trait Module extends mill.Module with TaskModule { outer => /** * Things that need to be on the classpath in order for this code to run */ - def runDepClasspath: T[Seq[PathRef]] = T{ - upstreamRunClasspath().flatten ++ + def runDepClasspath: T[OSet[PathRef]] = T{ + OSet.from(upstreamRunClasspath().flatten) ++ depClasspath() ++ resolveDeps( - T.task{ivyDeps() ++ runIvyDeps() ++ scalaRuntimeIvyDeps(scalaVersion())}, + T.task{ivyDeps() ++ runIvyDeps() ++ scalaRuntimeIvyDeps(scalaVersion())} )() } def prependShellScript: T[String] = T{ "" } - def sources = T.input{ Seq(PathRef(basePath / 'src)) } - def resources = T.input{ Seq(PathRef(basePath / 'resources)) } - def generatedSources = T { Seq.empty[PathRef] } + def sources = T.input{ OSet(PathRef(basePath / 'src)) } + def resources = T.input{ OSet(PathRef(basePath / 'resources)) } + def generatedSources = T { OSet.empty[PathRef] } def allSources = T{ sources() ++ generatedSources() } def compile: T[CompilationResult] = T.persistent{ compileScala( @@ -203,11 +204,11 @@ trait Module extends mill.Module with TaskModule { outer => subprocess( "scala.tools.nsc.ScalaDoc", - compileDepClasspath().filterNot(_.path.ext == "pom").map(_.path), - options = options + compileDepClasspath().filter(_.path.ext != "pom").map(_.path), + options = options.toSeq ) - createJar(Seq(javadocDir))(outDir / "javadoc.jar") + createJar(OSet(javadocDir))(outDir / "javadoc.jar") } def sourcesJar = T { @@ -283,7 +284,7 @@ trait TestModule extends Module with TaskModule { jvmOptions = forkArgs(), options = Seq( testFramework(), - runClasspath().map(_.path).distinct.mkString(" "), + runClasspath().map(_.path).mkString(" "), Seq(compile().classes.path).mkString(" "), args.mkString(" "), outputPath.toString, @@ -301,7 +302,7 @@ trait TestModule extends Module with TaskModule { val (doneMsg, results) = TestRunner( testFramework(), runClasspath().map(_.path), - Seq(compile().classes.path), + OSet(compile().classes.path), args ) TestModule.handleResults(doneMsg, results) diff --git a/scalalib/src/main/scala/mill/scalalib/PublishModule.scala b/scalalib/src/main/scala/mill/scalalib/PublishModule.scala index 1b1a0f44..211c94d2 100644 --- a/scalalib/src/main/scala/mill/scalalib/PublishModule.scala +++ b/scalalib/src/main/scala/mill/scalalib/PublishModule.scala @@ -3,7 +3,7 @@ package scalalib import ammonite.ops._ import mill.eval.{PathRef, Result} - +import mill.util.Loose.OSet /** * Configuration necessary for publishing a Scala module to Maven Central or similar */ diff --git a/scalalib/src/main/scala/mill/scalalib/TestRunner.scala b/scalalib/src/main/scala/mill/scalalib/TestRunner.scala index 0d1768f6..d129e0d4 100644 --- a/scalalib/src/main/scala/mill/scalalib/TestRunner.scala +++ b/scalalib/src/main/scala/mill/scalalib/TestRunner.scala @@ -8,7 +8,8 @@ import java.util.zip.ZipInputStream import ammonite.ops.{Path, ls, pwd} import ammonite.util.Colors import mill.util.Ctx.LogCtx -import mill.util.PrintLogger +import mill.util.{PrintLogger} +import mill.util.Loose.OSet import sbt.testing._ import upickle.Js import mill.util.JsonFormatters._ @@ -23,7 +24,7 @@ object TestRunner { Iterator.continually(zip.getNextEntry).takeWhile(_ != null).map(_.getName).filter(_.endsWith(".class")) } } - def runTests(cl: ClassLoader, framework: Framework, classpath: Seq[Path]) = { + def runTests(cl: ClassLoader, framework: Framework, classpath: OSet[Path]) = { val fingerprints = framework.fingerprints() @@ -48,8 +49,8 @@ object TestRunner { def main(args: Array[String]): Unit = { val result = apply( frameworkName = args(0), - entireClasspath = args(1).split(" ").map(Path(_)), - testClassfilePath = args(2).split(" ").map(Path(_)), + entireClasspath = OSet.from(args(1).split(" ").map(Path(_))), + testClassfilePath = OSet.from(args(2).split(" ").map(Path(_))), args = args(3) match{ case "" => Nil case x => x.split(" ").toList } )(new PrintLogger( args(5) == "true", @@ -69,8 +70,8 @@ object TestRunner { System.exit(0) } def apply(frameworkName: String, - entireClasspath: Seq[Path], - testClassfilePath: Seq[Path], + entireClasspath: OSet[Path], + testClassfilePath: OSet[Path], args: Seq[String]) (implicit ctx: LogCtx): (String, Seq[Result]) = { val outerClassLoader = getClass.getClassLoader diff --git a/scalalib/src/main/scala/mill/scalalib/publish/Ivy.scala b/scalalib/src/main/scala/mill/scalalib/publish/Ivy.scala index ff21c9ac..288b63d0 100644 --- a/scalalib/src/main/scala/mill/scalalib/publish/Ivy.scala +++ b/scalalib/src/main/scala/mill/scalalib/publish/Ivy.scala @@ -1,5 +1,7 @@ package mill.scalalib.publish +import mill.util.Loose.OSet + import scala.xml.PrettyPrinter object Ivy { @@ -8,7 +10,7 @@ object Ivy { def apply( artifact: Artifact, - dependencies: Seq[Dependency] + dependencies: OSet[Dependency] ): String = { val xml = diff --git a/scalalib/src/main/scala/mill/scalalib/publish/Pom.scala b/scalalib/src/main/scala/mill/scalalib/publish/Pom.scala index 32ad036a..c1ce3e2a 100644 --- a/scalalib/src/main/scala/mill/scalalib/publish/Pom.scala +++ b/scalalib/src/main/scala/mill/scalalib/publish/Pom.scala @@ -1,5 +1,7 @@ package mill.scalalib.publish +import mill.util.Loose.OSet + import scala.xml.{Elem, NodeSeq, PrettyPrinter} object Pom { @@ -8,7 +10,7 @@ object Pom { //TODO - not only jar packaging support? def apply(artifact: Artifact, - dependencies: Seq[Dependency], + dependencies: OSet[Dependency], name: String, pomSettings: PomSettings): String = { val xml = diff --git a/scalalib/src/test/scala/mill/scalalib/ResolveDepsTests.scala b/scalalib/src/test/scala/mill/scalalib/ResolveDepsTests.scala index c5a05d02..c4404fe6 100644 --- a/scalalib/src/test/scala/mill/scalalib/ResolveDepsTests.scala +++ b/scalalib/src/test/scala/mill/scalalib/ResolveDepsTests.scala @@ -4,34 +4,35 @@ import coursier.Cache import coursier.maven.MavenRepository import mill.eval.Result.{Failure, Success} import mill.eval.{PathRef, Result} +import mill.util.Loose.OSet import utest._ object ResolveDepsTests extends TestSuite { val repos = Seq(Cache.ivy2Local, MavenRepository("https://repo1.maven.org/maven2")) - def evalDeps(deps: Seq[Dep]): Result[Seq[PathRef]] = Lib.resolveDependencies(repos, "2.12.4", "2.12", deps) + def evalDeps(deps: OSet[Dep]): Result[OSet[PathRef]] = Lib.resolveDependencies(repos, "2.12.4", "2.12", deps) val tests = Tests { 'resolveValidDeps - { - val deps = Seq(Dep("com.lihaoyi", "pprint", "0.5.3")) + val deps = OSet(Dep("com.lihaoyi", "pprint", "0.5.3")) val Success(paths) = evalDeps(deps) assert(paths.nonEmpty) } 'errOnInvalidOrgDeps - { - val deps = Seq(Dep("xxx.yyy.invalid", "pprint", "0.5.3")) + val deps = OSet(Dep("xxx.yyy.invalid", "pprint", "0.5.3")) val Failure(errMsg) = evalDeps(deps) assert(errMsg.contains("xxx.yyy.invalid")) } 'errOnInvalidVersionDeps - { - val deps = Seq(Dep("com.lihaoyi", "pprint", "invalid.version.num")) + val deps = OSet(Dep("com.lihaoyi", "pprint", "invalid.version.num")) val Failure(errMsg) = evalDeps(deps) assert(errMsg.contains("invalid.version.num")) } 'errOnPartialSuccess - { - val deps = Seq(Dep("com.lihaoyi", "pprint", "0.5.3"), Dep("fake", "fake", "fake")) + val deps = OSet(Dep("com.lihaoyi", "pprint", "0.5.3"), Dep("fake", "fake", "fake")) val Failure(errMsg) = evalDeps(deps) assert(errMsg.contains("fake")) } diff --git a/shared.sc b/shared.sc index ef2f26d3..a475a449 100644 --- a/shared.sc +++ b/shared.sc @@ -74,7 +74,7 @@ def generateEval(dir: Path) = { s"""package mill.main |import mill.eval.Evaluator |import mill.define.Task - |import mill.util.OSet + |import mill.util.Strict.OSet |class EvalGenerated(evaluator: Evaluator[_]) { | type TT[+X] = Task[X] | ${(1 to 22).map(generate).mkString("\n")} -- cgit v1.2.3