From be3fa7e66d6939d42b6d36670aab31bec3f1d965 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 11 Apr 2017 11:48:24 +0100 Subject: [PATCH] Just whitespace & comment changes --- .../src/main/scala/sbt/Compiler.scala | 2 + .../src/main/scala/sbt/InputTask.scala | 1 + .../src/main/scala/sbt/Structure.scala | 4 +- .../src/main/scala/sbt/std/TaskMacro.scala | 21 +++++++++ main/src/main/scala/sbt/Defaults.scala | 23 ++++++++++ main/src/main/scala/sbt/EvaluateTask.scala | 12 +++++- main/src/main/scala/sbt/Main.scala | 1 + main/src/main/scala/sbt/Project.scala | 14 +++++- .../scala/sbt/internal/BuildStructure.scala | 2 +- .../main/scala/sbt/internal/BuildUtil.scala | 1 + .../sbt/internal/EvaluateConfigurations.scala | 17 ++++++-- main/src/main/scala/sbt/internal/Load.scala | 43 +++++++++++++++++++ .../main/scala/sbt/test/ScriptedTests.scala | 4 ++ 13 files changed, 138 insertions(+), 7 deletions(-) diff --git a/main-actions/src/main/scala/sbt/Compiler.scala b/main-actions/src/main/scala/sbt/Compiler.scala index f2a1a5f74..d8eef8f1f 100644 --- a/main-actions/src/main/scala/sbt/Compiler.scala +++ b/main-actions/src/main/scala/sbt/Compiler.scala @@ -16,6 +16,7 @@ import sbt.internal.util.CacheStore object Compiler { val DefaultMaxErrors = 100 + private[sbt] def defaultCompilerBridgeSource(sv: String): ModuleID = VersionNumber(sv) match { // 2.10 and before @@ -24,6 +25,7 @@ object Compiler { case VersionNumber(ns, _, _) if (ns.size == 3) && (ns(0) == 2) && (ns(1) == 11) => scalaCompilerBridgeSource2_11 case _ => scalaCompilerBridgeSource2_12 } + private[sbt] def scalaCompilerBridgeSource2_10: ModuleID = ModuleID(xsbti.ArtifactInfo.SbtOrganization, "compiler-bridge_2.10", ComponentCompiler.incrementalVersion).withConfigurations(Some("component")).sources() diff --git a/main-settings/src/main/scala/sbt/InputTask.scala b/main-settings/src/main/scala/sbt/InputTask.scala index c90f31f50..6e2e1ffdf 100644 --- a/main-settings/src/main/scala/sbt/InputTask.scala +++ b/main-settings/src/main/scala/sbt/InputTask.scala @@ -120,6 +120,7 @@ object InputTask { val t: Task[I] = Task(Info[I]().set(key, None), Pure(f, false)) (key, t) } + private[this] def subForDummy[I, T](marker: AttributeKey[Option[I]], value: I, task: Task[T]): Task[T] = { val seen = new java.util.IdentityHashMap[Task[_], Task[_]] diff --git a/main-settings/src/main/scala/sbt/Structure.scala b/main-settings/src/main/scala/sbt/Structure.scala index c06c34bf0..690a3f721 100644 --- a/main-settings/src/main/scala/sbt/Structure.scala +++ b/main-settings/src/main/scala/sbt/Structure.scala @@ -206,6 +206,7 @@ object Scoped { def ??[T >: S](or: => T): Initialize[Task[T]] = Def.optional(scopedKey)(_ getOrElse mktask(or)) def or[T >: S](i: Initialize[Task[T]]): Initialize[Task[T]] = (this.? zipWith i)((x, y) => (x, y) map { case (a, b) => a getOrElse b }) } + final class RichInitializeTask[S](i: Initialize[Task[S]]) extends RichInitTaskBase[S, Task] { protected def onTask[T](f: Task[S] => Task[T]): Initialize[Task[T]] = i apply f @@ -217,9 +218,11 @@ object Scoped { def xtriggeredBy[T](tasks: Initialize[Task[T]]*): Initialize[Task[S]] = nonLocal(tasks, Def.triggeredBy) def triggeredBy[T](tasks: Initialize[Task[T]]*): Initialize[Task[S]] = nonLocal(tasks, Def.triggeredBy) def runBefore[T](tasks: Initialize[Task[T]]*): Initialize[Task[S]] = nonLocal(tasks, Def.runBefore) + private[this] def nonLocal(tasks: Seq[AnyInitTask], key: AttributeKey[Seq[Task[_]]]): Initialize[Task[S]] = (Initialize.joinAny[Task](tasks), i) { (ts, i) => i.copy(info = i.info.set(key, ts)) } } + final class RichInitializeInputTask[S](i: Initialize[InputTask[S]]) extends RichInitTaskBase[S, InputTask] { protected def onTask[T](f: Task[S] => Task[T]): Initialize[InputTask[T]] = i(_ mapTask f) def dependsOn(tasks: AnyInitTask*): Initialize[InputTask[S]] = (i, Initialize.joinAny[Task](tasks)) { (thisTask, deps) => thisTask.mapTask(_.dependsOn(deps: _*)) } @@ -359,7 +362,6 @@ object Scoped { def identityMap = map(mkTuple10) protected def convert[M[_], R](z: Fun[M, R]) = z.tupled } - final class RichTaskable11[A, B, C, D, E, F, G, H, I, J, K](t11: ((ST[A], ST[B], ST[C], ST[D], ST[E], ST[F], ST[G], ST[H], ST[I], ST[J], ST[K]))) extends RichTaskables[AList.T11K[A, B, C, D, E, F, G, H, I, J, K]#l](t11)(AList.tuple11[A, B, C, D, E, F, G, H, I, J, K]) { type Fun[M[_], Ret] = (M[A], M[B], M[C], M[D], M[E], M[F], M[G], M[H], M[I], M[J], M[K]) => Ret def identityMap = map(mkTuple11) diff --git a/main-settings/src/main/scala/sbt/std/TaskMacro.scala b/main-settings/src/main/scala/sbt/std/TaskMacro.scala index eb0c1edbc..44b3a372d 100644 --- a/main-settings/src/main/scala/sbt/std/TaskMacro.scala +++ b/main-settings/src/main/scala/sbt/std/TaskMacro.scala @@ -129,18 +129,25 @@ object TaskMacro { def itaskAssignPosition[T: c.WeakTypeTag](c: blackbox.Context)(app: c.Expr[Initialize[Task[T]]]): c.Expr[Setting[Task[T]]] = settingAssignPosition(c)(app) + def taskAssignPositionT[T: c.WeakTypeTag](c: blackbox.Context)(app: c.Expr[Task[T]]): c.Expr[Setting[Task[T]]] = itaskAssignPosition(c)(c.universe.reify { Def.valueStrict(app.splice) }) + def taskAssignPositionPure[T: c.WeakTypeTag](c: blackbox.Context)(app: c.Expr[T]): c.Expr[Setting[Task[T]]] = taskAssignPositionT(c)(c.universe.reify { TaskExtra.constant(app.splice) }) + def taskTransformPosition[S: c.WeakTypeTag](c: blackbox.Context)(f: c.Expr[S => S]): c.Expr[Setting[Task[S]]] = c.Expr[Setting[Task[S]]](transformMacroImpl(c)(f.tree)(TransformInitName)) + def settingTransformPosition[S: c.WeakTypeTag](c: blackbox.Context)(f: c.Expr[S => S]): c.Expr[Setting[S]] = c.Expr[Setting[S]](transformMacroImpl(c)(f.tree)(TransformInitName)) + def itaskTransformPosition[S: c.WeakTypeTag](c: blackbox.Context)(f: c.Expr[S => S]): c.Expr[Setting[S]] = c.Expr[Setting[S]](transformMacroImpl(c)(f.tree)(TransformInitName)) + def settingAssignPure[T: c.WeakTypeTag](c: blackbox.Context)(app: c.Expr[T]): c.Expr[Setting[T]] = settingAssignPosition(c)(c.universe.reify { Def.valueStrict(app.splice) }) + def settingAssignPosition[T: c.WeakTypeTag](c: blackbox.Context)(app: c.Expr[Initialize[T]]): c.Expr[Setting[T]] = c.Expr[Setting[T]](transformMacroImpl(c)(app.tree)(AssignInitName)) @@ -151,6 +158,7 @@ object TaskMacro { val assign = transformMacroImpl(c)(init.tree)(AssignInitName) c.Expr[Setting[InputTask[T]]](assign) } + /** Implementation of += macro for tasks. */ def taskAppend1Impl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(v: c.Expr[U])(a: c.Expr[Append.Value[T, U]]): c.Expr[Setting[Task[T]]] = { @@ -158,6 +166,7 @@ object TaskMacro { val append = appendMacroImpl(c)(init.tree, a.tree)(Append1InitName) c.Expr[Setting[Task[T]]](append) } + /** Implementation of += macro for settings. */ def settingAppend1Impl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(v: c.Expr[U])(a: c.Expr[Append.Value[T, U]]): c.Expr[Setting[T]] = { @@ -179,6 +188,7 @@ object TaskMacro { c.Expr[Setting[T]](append) } } + /** Implementation of ++= macro for tasks. */ def taskAppendNImpl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(vs: c.Expr[U])(a: c.Expr[Append.Values[T, U]]): c.Expr[Setting[Task[T]]] = { @@ -186,6 +196,7 @@ object TaskMacro { val append = appendMacroImpl(c)(init.tree, a.tree)(AppendNInitName) c.Expr[Setting[Task[T]]](append) } + /** Implementation of ++= macro for settings. */ def settingAppendNImpl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(vs: c.Expr[U])(a: c.Expr[Append.Values[T, U]]): c.Expr[Setting[T]] = { @@ -193,6 +204,7 @@ object TaskMacro { val append = appendMacroImpl(c)(init.tree, a.tree)(AppendNInitName) c.Expr[Setting[T]](append) } + /** Implementation of -= macro for tasks. */ def taskRemove1Impl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(v: c.Expr[U])(r: c.Expr[Remove.Value[T, U]]): c.Expr[Setting[Task[T]]] = { @@ -200,6 +212,7 @@ object TaskMacro { val remove = removeMacroImpl(c)(init.tree, r.tree)(Remove1InitName) c.Expr[Setting[Task[T]]](remove) } + /** Implementation of -= macro for settings. */ def settingRemove1Impl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(v: c.Expr[U])(r: c.Expr[Remove.Value[T, U]]): c.Expr[Setting[T]] = { @@ -207,6 +220,7 @@ object TaskMacro { val remove = removeMacroImpl(c)(init.tree, r.tree)(Remove1InitName) c.Expr[Setting[T]](remove) } + /** Implementation of --= macro for tasks. */ def taskRemoveNImpl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(vs: c.Expr[U])(r: c.Expr[Remove.Values[T, U]]): c.Expr[Setting[Task[T]]] = { @@ -214,6 +228,7 @@ object TaskMacro { val remove = removeMacroImpl(c)(init.tree, r.tree)(RemoveNInitName) c.Expr[Setting[Task[T]]](remove) } + /** Implementation of --= macro for settings. */ def settingRemoveNImpl[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(vs: c.Expr[U])(r: c.Expr[Remove.Values[T, U]]): c.Expr[Setting[T]] = { @@ -231,6 +246,7 @@ object TaskMacro { case x => ContextUtil.unexpectedTree(x) } } + private[this] def removeMacroImpl(c: blackbox.Context)(init: c.Tree, remove: c.Tree)(newName: String): c.Tree = { import c.universe._ @@ -240,6 +256,7 @@ object TaskMacro { case x => ContextUtil.unexpectedTree(x) } } + private[this] def transformMacroImpl(c: blackbox.Context)(init: c.Tree)(newName: String): c.Tree = { import c.universe._ @@ -250,6 +267,7 @@ object TaskMacro { } Apply.apply(Select(target, TermName(newName).encodedName), init :: sourcePosition(c).tree :: Nil) } + private[this] def sourcePosition(c: blackbox.Context): c.Expr[SourcePosition] = { import c.universe.reify @@ -262,6 +280,7 @@ object TaskMacro { } else reify { NoPosition } } + private[this] def settingSource(c: blackbox.Context, path: String, name: String): String = { @tailrec def inEmptyPackage(s: c.Symbol): Boolean = s != c.universe.NoSymbol && ( @@ -281,6 +300,7 @@ object TaskMacro { def inputTaskMacroImpl[T: c.WeakTypeTag](c: blackbox.Context)(t: c.Expr[T]): c.Expr[Initialize[InputTask[T]]] = inputTaskMacro0[T](c)(t) + def inputTaskDynMacroImpl[T: c.WeakTypeTag](c: blackbox.Context)(t: c.Expr[Initialize[Task[T]]]): c.Expr[Initialize[InputTask[T]]] = inputTaskDynMacro0[T](c)(t) @@ -298,6 +318,7 @@ object TaskMacro { val cond = c.Expr[T](conditionInputTaskTree(c)(t.tree)) Instance.contImpl[T, M](c, InitializeInstance, InputInitConvert, MixedBuilder)(Left(cond), inner) } + private[this] def conditionInputTaskTree(c: blackbox.Context)(t: c.Tree): c.Tree = { import c.universe._ diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index a32faf52a..38b5c0dc3 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -441,6 +441,7 @@ object Defaults extends BuildCommon { scalaInstanceFromUpdate } } + // Returns the ScalaInstance only if it was not constructed via `update` // This is necessary to prevent cycles between `update` and `scalaInstance` private[sbt] def unmanagedScalaInstanceOnly: Initialize[Task[Option[ScalaInstance]]] = Def.taskDyn { @@ -527,6 +528,7 @@ object Defaults extends BuildCommon { )) ++ inScope(GlobalScope)(Seq( derive(testGrouping := singleTestGroupDefault.value) )) + @deprecated("Doesn't provide for closing the underlying resources.", "0.13.1") def testLogger(manager: Streams, baseKey: Scoped)(tdef: TestDefinition): Logger = { @@ -535,6 +537,7 @@ object Defaults extends BuildCommon { val key = ScopedKey(scope.copy(extra = Select(testExtra(extra, tdef))), baseKey.key) manager(key).log } + private[this] def closeableTestLogger(manager: Streams, baseKey: Scoped, buffered: Boolean)(tdef: TestDefinition): TestLogger.PerTest = { val scope = baseKey.scope @@ -543,6 +546,7 @@ object Defaults extends BuildCommon { val s = manager(key) new TestLogger.PerTest(s.log, () => s.close(), buffered) } + def buffered(log: Logger): Logger = new BufferedLogger(FullLogger(log)) def testExtra(extra: AttributeMap, tdef: TestDefinition): AttributeMap = { @@ -772,6 +776,7 @@ object Defaults extends BuildCommon { val f = artifactName.value (crossTarget.value / f(ScalaVersion((scalaVersion in artifactName).value, (scalaBinaryVersion in artifactName).value), projectID.value, art.value)).asFile } + def artifactSetting: Initialize[Artifact] = Def.setting { val a = artifact.value @@ -810,6 +815,7 @@ object Defaults extends BuildCommon { artifact := artifactSetting.value, artifactPath := artifactPathSetting(artifact).value )) + def packageTask: Initialize[Task[File]] = Def.task { val config = packageConfiguration.value @@ -817,12 +823,16 @@ object Defaults extends BuildCommon { Package(config, s.cacheStoreFactory, s.log) config.jar } + def packageConfigurationTask: Initialize[Task[Package.Configuration]] = Def.task { new Package.Configuration(mappings.value, artifactPath.value, packageOptions.value) } + def askForMainClass(classes: Seq[String]): Option[String] = sbt.SelectMainClass(Some(SimpleReader readLine _), classes) + def pickMainClass(classes: Seq[String]): Option[String] = sbt.SelectMainClass(None, classes) + private def pickMainClassOrWarn(classes: Seq[String], logger: Logger): Option[String] = { classes match { case multiple if multiple.size > 1 => logger.warn("Multiple main classes detected. Run 'show discoveredMainClasses' to see the list") @@ -952,6 +962,7 @@ object Defaults extends BuildCommon { @deprecated("Use `docTaskSettings` instead", "0.12.0") def docSetting(key: TaskKey[File]) = docTaskSettings(key) + def docTaskSettings(key: TaskKey[File] = doc): Seq[Setting[_]] = inTask(key)(Seq( apiMappings ++= { if (autoAPIMappings.value) APIMappings.extract(dependencyClasspath.value, streams.value.log).toMap else Map.empty[File, URL] }, fileInputOptions := Seq("-doc-root-content", "-diagrams-dot-path"), @@ -1192,6 +1203,7 @@ object Defaults extends BuildCommon { case _ => fullAgg } } + def getDependencies(structure: LoadedBuild, classpath: Boolean = true, aggregate: Boolean = false): ProjectRef => Seq[ProjectRef] = ref => Project.getProject(ref, structure).toList flatMap { p => (if (classpath) p.dependencies.map(_.project) else Nil) ++ @@ -1293,6 +1305,7 @@ object Classpaths { def packaged(pkgTasks: Seq[TaskKey[File]]): Initialize[Task[Map[Artifact, File]]] = enabledOnly(packagedArtifact.task, pkgTasks) apply (_.join.map(_.toMap)) + def artifactDefs(pkgTasks: Seq[TaskKey[File]]): Initialize[Seq[Artifact]] = enabledOnly(artifact, pkgTasks) @@ -1918,6 +1931,7 @@ object Classpaths { def deliverConfig(outputDirectory: File, status: String = "release", logging: UpdateLogging = UpdateLogging.DownloadOnly) = new DeliverConfiguration(deliverPattern(outputDirectory), status, None, logging) + @deprecated("Previous semantics allowed overwriting cached files, which was unsafe. Please specify overwrite parameter.", "0.13.2") def publishConfig(artifacts: Map[Artifact, File], ivyFile: Option[File], checksums: Seq[String], resolverName: String, logging: UpdateLogging): PublishConfiguration = publishConfig(artifacts, ivyFile, checksums, resolverName, logging, overwrite = true) @@ -1937,10 +1951,12 @@ object Classpaths { } } } + private[sbt] def depMap: Initialize[Task[Map[ModuleRevisionId, ModuleDescriptor]]] = Def.taskDyn { depMap(buildDependencies.value classpathTransitiveRefs thisProjectRef.value, settingsData.value, streams.value.log) } + private[sbt] def depMap(projects: Seq[ProjectRef], data: Settings[Scope], log: Logger): Initialize[Task[Map[ModuleRevisionId, ModuleDescriptor]]] = Def.value { projects.flatMap(ivyModule in _ get data).join.map { mod => @@ -2390,8 +2406,10 @@ trait BuildExtra extends BuildCommon with DefExtra { def externalIvySettings(file: Initialize[File] = inBase("ivysettings.xml"), addMultiResolver: Boolean = true): Setting[Task[IvyConfiguration]] = externalIvySettingsURI(file(_.toURI), addMultiResolver) + def externalIvySettingsURL(url: URL, addMultiResolver: Boolean = true): Setting[Task[IvyConfiguration]] = externalIvySettingsURI(Def.value(url.toURI), addMultiResolver) + def externalIvySettingsURI(uri: Initialize[URI], addMultiResolver: Boolean = true): Setting[Task[IvyConfiguration]] = { val other = Def.task { (baseDirectory.value, appConfiguration.value, projectResolver.value, updateOptions.value, streams.value) } @@ -2404,10 +2422,12 @@ trait BuildExtra extends BuildCommon with DefExtra { } }).value } + private[this] def inBase(name: String): Initialize[File] = Def.setting { baseDirectory.value / name } def externalIvyFile(file: Initialize[File] = inBase("ivy.xml"), iScala: Initialize[Option[IvyScala]] = ivyScala): Setting[Task[ModuleSettings]] = moduleSettings := IvyFileConfiguration(ivyValidate.value, iScala.value, file.value, managedScalaInstance.value) + def externalPom(file: Initialize[File] = inBase("pom.xml"), iScala: Initialize[Option[IvyScala]] = ivyScala): Setting[Task[ModuleSettings]] = moduleSettings := PomConfiguration(ivyValidate.value, ivyScala.value, file.value, managedScalaInstance.value) @@ -2419,6 +2439,7 @@ trait BuildExtra extends BuildCommon with DefExtra { val args = spaceDelimited().parsed r.run(mainClass, data(cp), baseArguments ++ args, streams.value.log).get } + def runTask(config: Configuration, mainClass: String, arguments: String*): Initialize[Task[Unit]] = Def.task { val cp = (fullClasspath in config).value @@ -2426,6 +2447,7 @@ trait BuildExtra extends BuildCommon with DefExtra { val s = streams.value r.run(mainClass, data(cp), arguments, s.log).get } + // public API /** Returns a vector of settings that create custom run input task. */ def fullRunInputTask(scoped: InputKey[Unit], config: Configuration, mainClass: String, baseArguments: String*): Vector[Setting[_]] = @@ -2467,6 +2489,7 @@ trait BuildExtra extends BuildCommon with DefExtra { def filterKeys(ss: Seq[Setting[_]], transitive: Boolean = false)(f: ScopedKey[_] => Boolean): Seq[Setting[_]] = ss filter (s => f(s.key) && (!transitive || s.dependencies.forall(f))) } + trait DefExtra { private[this] val ts: TaskSequential = new TaskSequential {} implicit def toTaskSequential(d: Def.type): TaskSequential = ts diff --git a/main/src/main/scala/sbt/EvaluateTask.scala b/main/src/main/scala/sbt/EvaluateTask.scala index d10ea5ba8..63045fca9 100644 --- a/main/src/main/scala/sbt/EvaluateTask.scala +++ b/main/src/main/scala/sbt/EvaluateTask.scala @@ -40,8 +40,9 @@ trait RunningTaskEngine { /** Attempts to kill and shutdown the running task engine.*/ def cancelAndShutdown(): Unit } + /** - * A strategy for being able to cancle tasks. + * A strategy for being able to cancel tasks. * * Implementations of this trait determine what will trigger `cancel()` for * the task engine, providing in the `start` method. @@ -51,6 +52,7 @@ trait RunningTaskEngine { trait TaskCancellationStrategy { /** The state used by this task. */ type State + /** * Called when task evaluation starts. * @@ -58,9 +60,11 @@ trait TaskCancellationStrategy { * @return Whatever state you need to cleanup in your finish method. */ def onTaskEngineStart(canceller: RunningTaskEngine): State + /** Called when task evaluation completes, either in success or failure. */ def onTaskEngineFinish(state: State): Unit } + object TaskCancellationStrategy { /** An empty handler that does not cancel tasks. */ object Null extends TaskCancellationStrategy { @@ -69,6 +73,7 @@ object TaskCancellationStrategy { def onTaskEngineFinish(state: Unit): Unit = () override def toString: String = "Null" } + /** Cancel handler which registers for SIGINT and cancels tasks when it is received. */ object Signal extends TaskCancellationStrategy { type State = Signals.Registration @@ -103,6 +108,7 @@ sealed trait EvaluateTaskConfig { */ def minForcegcInterval: Duration } + object EvaluateTaskConfig { @deprecated("Use the alternative that specifies minForcegcInterval", "0.13.9") def apply( @@ -207,15 +213,19 @@ object EvaluateTask { val extracted = Project.extract(state) restrictions(extracted, extracted.structure) } + def restrictions(extracted: Extracted, structure: BuildStructure): Seq[Tags.Rule] = getSetting(Keys.concurrentRestrictions, defaultRestrictions(extracted, structure), extracted, structure) + def maxWorkers(extracted: Extracted, structure: BuildStructure): Int = if (getSetting(Keys.parallelExecution, true, extracted, structure)) SystemProcessors else 1 + def cancelable(extracted: Extracted, structure: BuildStructure): Boolean = getSetting(Keys.cancelable, false, extracted, structure) + def cancelStrategy(extracted: Extracted, structure: BuildStructure, state: State): TaskCancellationStrategy = getSetting(Keys.taskCancelStrategy, { (_: State) => TaskCancellationStrategy.Null }, extracted, structure)(state) diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index 977956d70..0a6d0f3cb 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -570,6 +570,7 @@ object BuiltinCommands { SessionSettings.checkSession(session, s) Project.setProject(session, structure, s) } + def registerCompilerCache(s: State): State = { val maxCompilers = System.getProperty("sbt.resident.limit") diff --git a/main/src/main/scala/sbt/Project.scala b/main/src/main/scala/sbt/Project.scala index 8e2af71c2..6306e0ff7 100755 --- a/main/src/main/scala/sbt/Project.scala +++ b/main/src/main/scala/sbt/Project.scala @@ -69,10 +69,12 @@ sealed trait ProjectDefinition[PR <: ProjectReference] { private[sbt] def autoPlugins: Seq[AutoPlugin] override final def hashCode: Int = id.hashCode ^ base.hashCode ^ getClass.hashCode + override final def equals(o: Any) = o match { case p: ProjectDefinition[_] => p.getClass == this.getClass && p.id == id && p.base == base case _ => false } + override def toString = { val agg = ifNonEmpty("aggregate", aggregate) @@ -82,8 +84,10 @@ sealed trait ProjectDefinition[PR <: ProjectReference] { val fields = s"id $id" :: s"base: $base" :: agg ::: dep ::: conf ::: (s"plugins: List($plugins)" :: autos) s"Project(${fields.mkString(", ")})" } + private[this] def ifNonEmpty[T](label: String, ts: Iterable[T]): List[String] = if (ts.isEmpty) Nil else s"$label: $ts" :: Nil } + sealed trait Project extends ProjectDefinition[ProjectReference] { private[sbt] def settingsEval: Eval[Seq[Def.Setting[_]]] private[sbt] def aggregateEval: Eval[Seq[ProjectReference]] @@ -119,6 +123,7 @@ sealed trait Project extends ProjectDefinition[ProjectReference] { settingsEval, configurations, plugins, autoPlugins, projectOrigin) } + def resolveBuild(resolveRef: ProjectReference => ProjectReference): Project = { def resolveRefs(prs: Seq[ProjectReference]) = prs map resolveRef @@ -224,6 +229,7 @@ sealed trait Project extends ProjectDefinition[ProjectReference] { unresolved(id, base, aggregateEval = aggregateEval, dependenciesEval = dependenciesEval, delegatesEval = delegatesEval, settingsEval, configurations, plugins, autoPlugins, origin) } } + sealed trait ResolvedProject extends ProjectDefinition[ProjectRef] { /** The [[AutoPlugin]]s enabled for this project as computed from [[plugins]].*/ def autoPlugins: Seq[AutoPlugin] @@ -546,7 +552,6 @@ object Project extends ProjectExtra { def reverseDependencies(cMap: Map[ScopedKey[_], Flattened], scoped: ScopedKey[_]): Iterable[ScopedKey[_]] = for ((key, compiled) <- cMap; dep <- compiled.dependencies if dep == scoped) yield key - //@deprecated("Use SettingCompletions.setAll when available.", "0.13.0") def setAll(extracted: Extracted, settings: Seq[Def.Setting[_]]): SessionSettings = SettingCompletions.setAll(extracted, settings).session @@ -637,6 +642,7 @@ trait ProjectExtra0 { trait ProjectExtra extends ProjectExtra0 { implicit def classpathDependencyEval[T](p: => T)(implicit ev: T => ClasspathDep[ProjectReference]): Eval[ClasspathDep[ProjectReference]] = Eval.later(p: ClasspathDep[ProjectReference]) + implicit def wrapProjectReferenceEval[T](ref: => T)(implicit ev: T => ProjectReference): Eval[ProjectReference] = Eval.later(ref: ProjectReference) @@ -656,19 +662,25 @@ trait ProjectExtra extends ProjectExtra0 { def inThisBuild(ss: Seq[Setting[_]]): Seq[Setting[_]] = inScope(ThisScope.copy(project = Select(ThisBuild)))(ss) + def inConfig(conf: Configuration)(ss: Seq[Setting[_]]): Seq[Setting[_]] = inScope(ThisScope.copy(config = Select(conf)))((configuration :== conf) +: ss) + def inTask(t: Scoped)(ss: Seq[Setting[_]]): Seq[Setting[_]] = inScope(ThisScope.copy(task = Select(t.key)))(ss) + def inScope(scope: Scope)(ss: Seq[Setting[_]]): Seq[Setting[_]] = Project.transform(Scope.replaceThis(scope), ss) private[sbt] def inThisBuild[T](i: Initialize[T]): Initialize[T] = inScope(ThisScope.copy(project = Select(ThisBuild)), i) + private[sbt] def inConfig[T](conf: Configuration, i: Initialize[T]): Initialize[T] = inScope(ThisScope.copy(config = Select(conf)), i) + private[sbt] def inTask[T](t: Scoped, i: Initialize[T]): Initialize[T] = inScope(ThisScope.copy(task = Select(t.key)), i) + private[sbt] def inScope[T](scope: Scope, i: Initialize[T]): Initialize[T] = i mapReferenced Project.mapScope(Scope.replaceThis(scope)) diff --git a/main/src/main/scala/sbt/internal/BuildStructure.scala b/main/src/main/scala/sbt/internal/BuildStructure.scala index 36c507988..c39ad10ac 100644 --- a/main/src/main/scala/sbt/internal/BuildStructure.scala +++ b/main/src/main/scala/sbt/internal/BuildStructure.scala @@ -166,7 +166,6 @@ final class DetectedPlugins(val autoPlugins: Seq[DetectedAutoPlugin], val builds private[this] def autoImports(pluginNames: Seq[String]) = pluginNames.map(_ + ".autoImport") private[this] def nonTopLevelPlugin(name: String) = name.contains('.') - } /** @@ -181,6 +180,7 @@ final class LoadedPlugins(val base: File, val pluginData: PluginData, val loader def fullClasspath: Seq[Attributed[File]] = pluginData.classpath def classpath = data(fullClasspath) } + /** * The loaded, but unresolved build unit. * @param uri The uniquely identifying URI for the build. diff --git a/main/src/main/scala/sbt/internal/BuildUtil.scala b/main/src/main/scala/sbt/internal/BuildUtil.scala index 1cfda382e..62f949cc9 100644 --- a/main/src/main/scala/sbt/internal/BuildUtil.scala +++ b/main/src/main/scala/sbt/internal/BuildUtil.scala @@ -84,6 +84,7 @@ object BuildUtil { /** Import just the names. */ def importNames(names: Seq[String]): Seq[String] = if (names.isEmpty) Nil else names.mkString("import ", ", ", "") :: Nil + /** Prepend `_root_` and import just the names. */ def importNamesRoot(names: Seq[String]): Seq[String] = importNames(names map rootedName) diff --git a/main/src/main/scala/sbt/internal/EvaluateConfigurations.scala b/main/src/main/scala/sbt/internal/EvaluateConfigurations.scala index 52a06012c..c0a444ce0 100644 --- a/main/src/main/scala/sbt/internal/EvaluateConfigurations.scala +++ b/main/src/main/scala/sbt/internal/EvaluateConfigurations.scala @@ -23,8 +23,6 @@ import sbt.io.IO * 1. Parsing high-level constructs (definitions, settings, imports) * 2. Compiling scala code into local .class files * 3. Evaluating the expressions and obtaining in-memory objects of the results (Setting[_] instances, or val references). - * - * */ private[sbt] object EvaluateConfigurations { @@ -46,7 +44,6 @@ private[sbt] object EvaluateConfigurations { * return a parsed, compiled + evaluated [[LoadedSbtFile]]. The result has * raw sbt-types that can be accessed and used. */ - @deprecated("We no longer merge build.sbt files together unless they are in the same directory.", "0.13.6") def apply(eval: Eval, srcs: Seq[File], imports: Seq[String]): LazyClassLoaded[LoadedSbtFile] = { val loadFiles = srcs.sortBy(_.getName) map { src => evaluateSbtFile(eval, src, IO.readLines(src), imports, 0) } @@ -142,13 +139,17 @@ private[sbt] object EvaluateConfigurations { new LoadedSbtFile(settings, projects, importDefs, manipulations, definitions, allGeneratedFiles) } } + /** move a project to be relative to this file after we've evaluated it. */ private[this] def resolveBase(f: File, p: Project) = p.copy(base = IO.resolve(f, p.base)) + @deprecated("Will no longer be public.", "0.13.6") def flatten(mksettings: Seq[ClassLoader => Seq[Setting[_]]]): ClassLoader => Seq[Setting[_]] = loader => mksettings.flatMap(_ apply loader) + def addOffset(offset: Int, lines: Seq[(String, Int)]): Seq[(String, Int)] = lines.map { case (s, i) => (s, i + offset) } + def addOffsetToRange(offset: Int, ranges: Seq[(String, LineRange)]): Seq[(String, LineRange)] = ranges.map { case (s, r) => (s, r shift offset) } @@ -226,19 +227,23 @@ private[sbt] object EvaluateConfigurations { private[this] def splitSettingsDefinitions(lines: Seq[(String, LineRange)]): (Seq[(String, LineRange)], Seq[(String, LineRange)]) = lines partition { case (line, range) => isDefinition(line) } + private[this] def isDefinition(line: String): Boolean = { val trimmed = line.trim DefinitionKeywords.exists(trimmed startsWith _) } + private[this] def extractedValTypes: Seq[String] = Seq(classOf[Project], classOf[InputKey[_]], classOf[TaskKey[_]], classOf[SettingKey[_]]).map(_.getName) + private[this] def evaluateDefinitions(eval: Eval, name: String, imports: Seq[(String, Int)], definitions: Seq[(String, LineRange)], file: Option[File]): compiler.EvalDefinitions = { val convertedRanges = definitions.map { case (s, r) => (s, r.start to r.end) } eval.evalDefinitions(convertedRanges, new EvalImports(imports, name), name, file, extractedValTypes) } } + object Index { def taskToKeyMap(data: Settings[Scope]): Map[Task[_], ScopedKey[Task[_]]] = { @@ -247,10 +252,13 @@ object Index { val pairs = for (scope <- data.scopes; AttributeEntry(key, value: Task[_]) <- data.data(scope).entries) yield (value, ScopedKey(scope, key.asInstanceOf[AttributeKey[Task[_]]])) // unclear why this cast is needed even with a type test in the above filter pairs.toMap[Task[_], ScopedKey[Task[_]]] } + def allKeys(settings: Seq[Setting[_]]): Set[ScopedKey[_]] = settings.flatMap(s => if (s.key.key.isLocal) Nil else s.key +: s.dependencies).filter(!_.key.isLocal).toSet + def attributeKeys(settings: Settings[Scope]): Set[AttributeKey[_]] = settings.data.values.flatMap(_.keys).toSet[AttributeKey[_]] + def stringToKeyMap(settings: Set[AttributeKey[_]]): Map[String, AttributeKey[_]] = stringToKeyMap0(settings)(_.label) @@ -263,7 +271,9 @@ object Index { else sys.error(duplicates map { case (k, tps) => "'" + k + "' (" + tps.mkString(", ") + ")" } mkString ("Some keys were defined with the same name but different types: ", ", ", "")) } + private[this]type TriggerMap = collection.mutable.HashMap[Task[_], Seq[Task[_]]] + def triggers(ss: Settings[Scope]): Triggers[Task] = { val runBefore = new TriggerMap @@ -276,6 +286,7 @@ object Index { val onComplete = Keys.onComplete in GlobalScope get ss getOrElse { () => () } new Triggers[Task](runBefore, triggeredBy, map => { onComplete(); map }) } + private[this] def update(map: TriggerMap, base: Task[_], tasksOpt: Option[Seq[Task[_]]]): Unit = for (tasks <- tasksOpt; task <- tasks) map(task) = base +: map.getOrElse(task, Nil) diff --git a/main/src/main/scala/sbt/internal/Load.scala b/main/src/main/scala/sbt/internal/Load.scala index 9ed09ee1c..ea07c0d7b 100755 --- a/main/src/main/scala/sbt/internal/Load.scala +++ b/main/src/main/scala/sbt/internal/Load.scala @@ -83,14 +83,17 @@ private[sbt] object Load { LoadBuildConfiguration(stagingDirectory, classpath, loader, compilers, evalPluginDef, delegates, EvaluateTask.injectStreams, pluginMgmt, inject, None, Nil, log) } + private def bootIvyHome(app: xsbti.AppConfiguration): Option[File] = try { Option(app.provider.scalaProvider.launcher.ivyHome) } catch { case _: NoSuchMethodError => None } + def injectGlobal(state: State): Seq[Setting[_]] = (appConfiguration in GlobalScope :== state.configuration) +: LogManager.settingsLogger(state) +: DefaultBackgroundJobService.backgroundJobServiceSetting +: EvaluateTask.injectSettings + def defaultWithGlobal(state: State, base: File, rawConfig: LoadBuildConfiguration, globalBase: File, log: Logger): LoadBuildConfiguration = { val globalPluginsDir = getGlobalPluginsDirectory(state, globalBase) @@ -105,6 +108,7 @@ private[sbt] object Load { if (files.isEmpty || base == globalBase) const(Nil) else buildGlobalSettings(globalBase, files, config) config.copy(injectSettings = config.injectSettings.copy(projectLoaded = compiled)) } + def buildGlobalSettings(base: File, files: Seq[File], config: LoadBuildConfiguration): ClassLoader => Seq[Setting[_]] = { val eval = mkEval(data(config.globalPluginClasspath), base, defaultEvalOptions) @@ -141,11 +145,13 @@ private[sbt] object Load { (project, extra) => Nil ) } + def configInherit(lb: LoadedBuild, ref: ResolvedReference, config: ConfigKey, rootProject: URI => String): Seq[ConfigKey] = ref match { case pr: ProjectRef => configInheritRef(lb, pr, config) case BuildRef(uri) => configInheritRef(lb, ProjectRef(uri, rootProject(uri)), config) } + def configInheritRef(lb: LoadedBuild, ref: ProjectRef, config: ConfigKey): Seq[ConfigKey] = configurationOpt(lb.units, ref.build, ref.project, config).toList.flatMap(_.extendsConfigs).map(c => ConfigKey(c.name)) @@ -220,6 +226,7 @@ private[sbt] object Load { } ss.map(s => s mapConstant setResolved(s.key) mapReferenced mapSpecial(s.key) mapInit setDefining) } + def setDefinitionKey[T](tk: Task[T], key: ScopedKey[_]): Task[T] = if (isDummy(tk)) tk else Task(tk.info.set(Keys.taskDefinitionKey, key), tk.work) @@ -245,6 +252,7 @@ private[sbt] object Load { } def isProjectThis(s: Setting[_]) = s.key.scope.project match { case This | Select(ThisProject) => true; case _ => false } + def buildConfigurations(loaded: LoadedBuild, rootProject: URI => String, injectSettings: InjectSettings): Seq[Setting[_]] = { ((loadedBuild in GlobalScope :== loaded) +: @@ -271,8 +279,10 @@ private[sbt] object Load { def transformProjectOnly(uri: URI, rootProject: URI => String, settings: Seq[Setting[_]]): Seq[Setting[_]] = Project.transform(Scope.resolveProject(uri, rootProject), settings) + def transformSettings(thisScope: Scope, uri: URI, rootProject: URI => String, settings: Seq[Setting[_]]): Seq[Setting[_]] = Project.transform(Scope.resolveScope(thisScope, uri, rootProject), settings) + def projectScope(project: Reference): Scope = Scope(Select(project), Global, Global, Global) def lazyEval(unit: BuildUnit): () => Eval = @@ -280,9 +290,12 @@ private[sbt] object Load { lazy val eval = mkEval(unit) () => eval } + def mkEval(unit: BuildUnit): Eval = mkEval(unit.definitions, unit.plugins, unit.plugins.pluginData.scalacOptions) + def mkEval(defs: LoadedDefinitions, plugs: LoadedPlugins, options: Seq[String]): Eval = mkEval(defs.target ++ plugs.classpath, defs.base, options) + def mkEval(classpath: Seq[File], base: File, options: Seq[String]): Eval = new Eval(options, classpath, s => new ConsoleReporter(s), Some(evalOutputDirectory(base))) @@ -316,6 +329,7 @@ private[sbt] object Load { def load(file: File, s: State, config: LoadBuildConfiguration): PartBuild = load(file, builtinLoader(s, config.copy(pluginManagement = config.pluginManagement.shift, extraBuilds = Nil)), config.extraBuilds.toList) + def builtinLoader(s: State, config: LoadBuildConfiguration): BuildLoader = { val fail = (uri: URI) => sys.error("Invalid build URI (no handler available): " + uri) @@ -325,7 +339,9 @@ private[sbt] object Load { val components = BuildLoader.components(resolver, build, full = BuildLoader.componentLoader) BuildLoader(components, fail, s, config) } + def load(file: File, loaders: BuildLoader, extra: List[URI]): PartBuild = loadURI(IO.directoryURI(file), loaders, extra) + def loadURI(uri: URI, loaders: BuildLoader, extra: List[URI]): PartBuild = { IO.assertAbsolute(uri) @@ -334,6 +350,7 @@ private[sbt] object Load { val build = new PartBuild(uri, map) newLoaders transformAll build } + def addOverrides(unit: BuildUnit, loaders: BuildLoader): BuildLoader = loaders updatePluginManagement PluginManagement.extractOverrides(unit.plugins.fullClasspath) @@ -363,6 +380,7 @@ private[sbt] object Load { val rootProjects = if (projectsInRoot.isEmpty) firstDefined :: Nil else projectsInRoot (new PartBuildUnit(unit, defined.map(d => (d.id, d)).toMap, rootProjects.map(_.id), buildSettings(unit)), externals) } + def buildSettings(unit: BuildUnit): Seq[Setting[_]] = { val buildScope = GlobalScope.copy(project = Select(BuildRef(unit.uri))) @@ -385,11 +403,14 @@ private[sbt] object Load { } case Nil => (references, builds, loaders) } + def checkProjectBase(buildBase: File, projectBase: File): Unit = { checkDirectory(projectBase) assert(buildBase == projectBase || IO.relativize(buildBase, projectBase).isDefined, "Directory " + projectBase + " is not contained in build root " + buildBase) } + def checkBuildBase(base: File) = checkDirectory(base) + def checkDirectory(base: File): Unit = { assert(base.isAbsolute, "Not absolute: " + base) if (base.isFile) @@ -397,6 +418,7 @@ private[sbt] object Load { else if (!base.exists) IO createDirectory base } + def resolveAll(builds: Map[URI, PartBuildUnit]): Map[URI, LoadedBuildUnit] = { val rootProject = getRootProject(builds) @@ -405,6 +427,7 @@ private[sbt] object Load { (uri, unit.resolveRefs(ref => Scope.resolveProjectRef(uri, rootProject, ref))) } } + def checkAll(referenced: Map[URI, List[ProjectReference]], builds: Map[URI, PartBuildUnit]): Unit = { val rootProject = getRootProject(builds) for ((uri, refs) <- referenced; ref <- refs) { @@ -427,6 +450,7 @@ private[sbt] object Load { } p => p.copy(base = resolve(p.base)) } + def resolveProjects(loaded: PartBuild): LoadedBuild = { val rootProject = getRootProject(loaded.units) @@ -437,12 +461,14 @@ private[sbt] object Load { } new LoadedBuild(loaded.root, units) } + def resolveProjects(uri: URI, unit: PartBuildUnit, rootProject: URI => String): LoadedBuildUnit = { IO.assertAbsolute(uri) val resolve = (_: Project).resolve(ref => Scope.resolveProjectRef(uri, rootProject, ref)) new LoadedBuildUnit(unit.unit, unit.defined mapValues resolve, unit.rootProjects, unit.buildSettings) } + def projects(unit: BuildUnit): Seq[Project] = { // we don't have the complete build graph loaded, so we don't have the rootProject function yet. @@ -451,15 +477,19 @@ private[sbt] object Load { // although the default loader will resolve the project base directory, other loaders may not, so run resolveBase here as well unit.definitions.projects.map(resolveBuild compose resolveBase(unit.localBase)) } + def getRootProject(map: Map[URI, BuildUnitBase]): URI => String = uri => getBuild(map, uri).rootProjects.headOption getOrElse emptyBuild(uri) + def getConfiguration(map: Map[URI, LoadedBuildUnit], uri: URI, id: String, conf: ConfigKey): Configuration = configurationOpt(map, uri, id, conf) getOrElse noConfiguration(uri, id, conf.name) + def configurationOpt(map: Map[URI, LoadedBuildUnit], uri: URI, id: String, conf: ConfigKey): Option[Configuration] = getProject(map, uri, id).configurations.find(_.name == conf.name) def getProject(map: Map[URI, LoadedBuildUnit], uri: URI, id: String): ResolvedProject = getBuild(map, uri).defined.getOrElse(id, noProject(uri, id)) + def getBuild[T](map: Map[URI, T], uri: URI): T = map.getOrElse(uri, noBuild(uri)) @@ -551,6 +581,7 @@ private[sbt] object Load { // Lame hackery to keep track of our state. private[this] case class LoadedProjects(projects: Seq[Project], generatedConfigClassFiles: Seq[File]) + /** * Loads a new set of projects, including any transitively defined projects underneath this one. * @@ -808,6 +839,7 @@ private[sbt] object Load { case Some(cp) => cp.data.fullClasspath case None => Nil } + /** These are the settings defined when loading a project "meta" build. */ val autoPluginSettings: Seq[Setting[_]] = inScope(GlobalScope in LocalRootProject)(Seq( sbtPlugin :== true, @@ -819,6 +851,7 @@ private[sbt] object Load { }, onLoadMessage := ("Loading project definition from " + baseDirectory.value) )) + private[this] def removeEntries(cp: Seq[Attributed[File]], remove: Seq[Attributed[File]]): Seq[Attributed[File]] = { val files = data(remove).toSet @@ -830,11 +863,13 @@ private[sbt] object Load { global = autoPluginSettings ++ config.injectSettings.global, project = config.pluginManagement.inject ++ config.injectSettings.project )) + def activateGlobalPlugin(config: LoadBuildConfiguration): LoadBuildConfiguration = config.globalPlugin match { case Some(gp) => config.copy(injectSettings = config.injectSettings.copy(project = gp.inject)) case None => config } + def plugins(dir: File, s: State, config: LoadBuildConfiguration): LoadedPlugins = if (hasDefinition(dir)) buildPlugins(dir, s, enableSbtPlugin(activateGlobalPlugin(config))) @@ -846,8 +881,10 @@ private[sbt] object Load { import sbt.io.syntax._ (dir * -GlobFilter(DefaultTargetName)).get.nonEmpty } + def noPlugins(dir: File, config: LoadBuildConfiguration): LoadedPlugins = loadPluginDefinition(dir, config, PluginData(config.globalPluginClasspath, Nil, None, None, Nil)) + def buildPlugins(dir: File, s: State, config: LoadBuildConfiguration): LoadedPlugins = loadPluginDefinition(dir, config, buildPluginDefinition(dir, s, config)) @@ -856,10 +893,13 @@ private[sbt] object Load { val (definitionClasspath, pluginLoader) = pluginDefinitionLoader(config, pluginData) loadPlugins(dir, pluginData.copy(dependencyClasspath = definitionClasspath), pluginLoader) } + def pluginDefinitionLoader(config: LoadBuildConfiguration, dependencyClasspath: Seq[Attributed[File]]): (Seq[Attributed[File]], ClassLoader) = pluginDefinitionLoader(config, dependencyClasspath, Nil) + def pluginDefinitionLoader(config: LoadBuildConfiguration, pluginData: PluginData): (Seq[Attributed[File]], ClassLoader) = pluginDefinitionLoader(config, pluginData.dependencyClasspath, pluginData.definitionClasspath) + def pluginDefinitionLoader(config: LoadBuildConfiguration, depcp: Seq[Attributed[File]], defcp: Seq[Attributed[File]]): (Seq[Attributed[File]], ClassLoader) = { val definitionClasspath = @@ -881,6 +921,7 @@ private[sbt] object Load { } (definitionClasspath, pluginLoader) } + def buildPluginDefinition(dir: File, s: State, config: LoadBuildConfiguration): PluginData = { val (eval, pluginDef) = apply(dir, s, config) @@ -950,6 +991,7 @@ private[sbt] object Load { def referenced[PR <: ProjectReference](definitions: Seq[ProjectDefinition[PR]]): Seq[PR] = definitions flatMap { _.referenced } final class EvaluatedConfigurations(val eval: Eval, val settings: Seq[Setting[_]]) + final case class InjectSettings(global: Seq[Setting[_]], project: Seq[Setting[_]], projectLoaded: ClassLoader => Seq[Setting[_]]) { import java.net.URLClassLoader private val cache: mutable.Map[String, Seq[Setting[_]]] = mutable.Map.empty @@ -1009,6 +1051,7 @@ final case class LoadBuildConfiguration( } Load.loadPluginDefinition(baseDir, this, pluginData) } + lazy val detectedGlobalPlugins = globalPluginDefs.detected } diff --git a/scripted/sbt/src/main/scala/sbt/test/ScriptedTests.scala b/scripted/sbt/src/main/scala/sbt/test/ScriptedTests.scala index 8b78e3f03..c90c1ccf9 100644 --- a/scripted/sbt/src/main/scala/sbt/test/ScriptedTests.scala +++ b/scripted/sbt/src/main/scala/sbt/test/ScriptedTests.scala @@ -153,15 +153,19 @@ class ScriptedRunner { } runAll(allTests) } + def runAll(tests: Seq[() => Option[String]]): Unit = { val errors = for (test <- tests; err <- test()) yield err if (errors.nonEmpty) sys.error(errors.mkString("Failed tests:\n\t", "\n\t", "\n")) } + def get(tests: Seq[String], baseDirectory: File, log: Logger): Seq[ScriptedTest] = if (tests.isEmpty) listTests(baseDirectory, log) else parseTests(tests) + def listTests(baseDirectory: File, log: Logger): Seq[ScriptedTest] = (new ListTests(baseDirectory, _ => true, log)).listTests + def parseTests(in: Seq[String]): Seq[ScriptedTest] = for (testString <- in) yield { val Array(group, name) = testString.split("/").map(_.trim)