Merge pull request #3834 from dwijnand/exclusive-cleaning

[sbt 0.13] Fix logging + clean concurrency issue
This commit is contained in:
eugene yokota 2018-01-02 20:30:42 -05:00 committed by GitHub
commit 160875e940
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 16 deletions

View File

@ -343,8 +343,9 @@ object Defaults extends BuildCommon {
lazy val projectTasks: Seq[Setting[_]] = Seq(
cleanFiles := Seq(managedDirectory.value, target.value),
cleanKeepFiles := historyPath.value.toList,
clean := doClean(cleanFiles.value, cleanKeepFiles.value),
cleanFilesTask := cleanFilesImpl.value,
cleanKeepFiles := historyPath.value.toVector,
clean := (Def.task { IO.delete(cleanFilesTask.value) } tag (Tags.Clean)).value,
consoleProject := consoleProjectTask.value,
watchTransitiveSources := watchTransitiveSourcesTask.value,
watch := watchSetting.value
@ -647,10 +648,15 @@ object Defaults extends BuildCommon {
def detectTests: Initialize[Task[Seq[TestDefinition]]] = (loadedTestFrameworks, compile, streams) map { (frameworkMap, analysis, s) =>
Tests.discover(frameworkMap.values.toList, analysis, s.log)._1
}
def defaultRestrictions: Initialize[Seq[Tags.Rule]] = parallelExecution { par =>
val max = EvaluateTask.SystemProcessors
Tags.limitAll(if (par) max else 1) :: Tags.limit(Tags.ForkedTestGroup, 1) :: Nil
}
def defaultRestrictions: Initialize[Seq[Tags.Rule]] =
Def.setting {
val par = parallelExecution.value
val max = EvaluateTask.SystemProcessors
Tags.limitAll(if (par) max else 1) ::
Tags.limit(Tags.ForkedTestGroup, 1) ::
Tags.exclusiveGroup(Tags.Clean) ::
Nil
}
lazy val packageBase: Seq[Setting[_]] = Seq(
artifact := Artifact(moduleName.value)
@ -775,15 +781,23 @@ object Defaults extends BuildCommon {
pickMainClass(classes)
}
def doClean(clean: Seq[File], preserve: Seq[File]): Unit =
IO.withTemporaryDirectory { temp =>
val (dirs, files) = preserve.filter(_.exists).flatMap(_.***.get).partition(_.isDirectory)
val mappings = files.zipWithIndex map { case (f, i) => (f, new File(temp, i.toHexString)) }
IO.move(mappings)
IO.delete(clean)
IO.createDirectories(dirs) // recreate empty directories
IO.move(mappings.map(_.swap))
/** Implements `cleanFilesTask` */
def cleanFilesImpl: Initialize[Task[Vector[File]]] =
Def.task {
val filesAndDirs = Vector(managedDirectory.value, target.value)
val preserve = cleanKeepFiles.value
val (dirs, fs) = filesAndDirs.filter(_.exists).partition(_.isDirectory)
val preserveSet = preserve.filter(_.exists).toSet
// performance reasons, only the direct items under `filesAndDirs` are allowed to be preserved.
val dirItems = dirs flatMap { _.*("*").get }
(preserveSet diff dirItems.toSet) match {
case xs if xs.isEmpty => ()
case xs => sys.error(s"cleanKeepFiles contains directory/file that are not directly under cleanFiles: $xs")
}
val toClean = (dirItems filterNot { preserveSet(_) }) ++ fs
toClean
}
def runMainTask(classpath: Initialize[Task[Classpath]], scalaRun: Initialize[Task[ScalaRun]]): Initialize[InputTask[Unit]] =
{
import DefaultParsers._

View File

@ -108,7 +108,8 @@ object Keys {
@deprecated("Use the cacheDirectory provided by streams.", "0.13.0")
val cacheDirectory = SettingKey[File]("cache-directory", "Directory used for caching task data.", BMinusSetting)
val cleanFiles = SettingKey[Seq[File]]("clean-files", "The files to recursively delete during a clean.", BSetting)
val cleanKeepFiles = SettingKey[Seq[File]]("clean-keep-files", "Files to keep during a clean.", CSetting)
val cleanFilesTask = TaskKey[Seq[File]]("clean-files-task", "The files to recursively delete during a clean.", BSetting)
val cleanKeepFiles = SettingKey[Seq[File]]("clean-keep-files", "Files or directories to keep during a clean. Must be direct children of target.", CSetting)
val crossPaths = SettingKey[Boolean]("cross-paths", "If true, enables cross paths, which distinguish input and output directories for cross-building.", ASetting)
val taskTemporaryDirectory = SettingKey[File]("task-temporary-directory", "Directory used for temporary files for tasks that is deleted after each task execution.", DSetting)

View File

@ -13,6 +13,7 @@ object Tags {
val Test = Tag("test")
val Update = Tag("update")
val Publish = Tag("publish")
val Clean = Tag("clean")
val CPU = Tag("cpu")
val Network = Tag("network")
@ -111,4 +112,4 @@ object Tags {
val groups = exclusiveTags.count(tag => tags.getOrElse(tag, 0) > 0)
groups <= 1
}
}
}