diff --git a/build.sbt b/build.sbt new file mode 100644 index 000000000..06cbf7a66 --- /dev/null +++ b/build.sbt @@ -0,0 +1,564 @@ +import Project.Initialize +import Util._ +import Dependencies._ +import Licensed._ +import Scope.ThisScope +import LaunchProguard.{ proguard, Proguard } +import Scripted._ +import StringUtilities.normalize +import Sxr.sxr + +def commonSettings: Seq[Setting[_]] = Seq( + organization := "org.scala-sbt", + version := "0.13.8-SNAPSHOT", + scalaVersion in ThisBuild := "2.10.4", + publishArtifact in packageDoc := false, + publishMavenStyle := false, + componentID := None, + crossPaths := false, + resolvers += Resolver.typesafeIvyRepo("releases"), + concurrentRestrictions in Global += Util.testExclusiveRestriction, + testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-w", "1"), + javacOptions in compile ++= Seq("-target", "6", "-source", "6", "-Xlint", "-Xlint:-serial"), + incOptions := incOptions.value.withNameHashing(true) +) + +def minimalSettings: Seq[Setting[_]] = + commonSettings ++ customCommands ++ Status.settings ++ + publishPomSettings ++ Release.javaVersionCheckSettings + +def baseSettings: Seq[Setting[_]] = + minimalSettings ++ Seq(projectComponent) ++ baseScalacOptions ++ Licensed.settings ++ Formatting.settings + +def testedBaseSettings: Seq[Setting[_]] = + baseSettings ++ testDependencies + +lazy val root: Project = (project in file(".")). + configs(Sxr.sxrConf, Proguard). + aggregate(nonRoots: _*). + settings(minimalSettings ++ rootSettings: _*) + +/* ** subproject declarations ** */ + +// defines the Java interfaces through which the launcher and the launched application communicate +lazy val launchInterfaceProj = (project in launchPath / "interface"). + settings(minimalSettings ++ javaOnlySettings: _*). + settings( + name := "Launcher Interface" + ) + +// the launcher. Retrieves, loads, and runs applications based on a configuration file. +lazy val launchProj = (project in launchPath). + dependsOn(ioProj % "test->test", interfaceProj % Test, launchInterfaceProj). + settings(testedBaseSettings: _*). + settings( + name := "Launcher", + libraryDependencies += ivy, + compile in Test <<= compile in Test dependsOn (publishLocal in interfaceProj, publishLocal in testSamples, publishLocal in launchInterfaceProj) + ). + settings(inConfig(Compile)(Transform.configSettings): _*). + settings(inConfig(Compile)(Transform.transSourceSettings ++ Seq( + Transform.inputSourceDirectory <<= (sourceDirectory in crossProj) / "input_sources", + Transform.sourceProperties := Map("cross.package0" -> "xsbt", "cross.package1" -> "boot") + )): _*) + +// used to test the retrieving and loading of an application: sample app is packaged and published to the local repository +lazy val testSamples = (project in launchPath / "test-sample"). + dependsOn(interfaceProj, launchInterfaceProj). + settings(baseSettings ++ noPublishSettings: _*). + settings( + name := "Launch Test", + libraryDependencies += scalaCompiler.value + ) + +// defines Java structures used across Scala versions, such as the API structures and relationships extracted by +// the analysis compiler phases and passed back to sbt. The API structures are defined in a simple +// format from which Java sources are generated by the datatype generator Projproject +lazy val interfaceProj = (project in file("interface")). + settings(minimalSettings ++ javaOnlySettings: _*). + settings( + name := "Interface", + projectComponent, + exportJars := true, + componentID := Some("xsbti"), + watchSources <++= apiDefinitions, + resourceGenerators in Compile <+= (version, resourceManaged, streams, compile in Compile) map generateVersionFile, + apiDefinitions <<= baseDirectory map { base => (base / "definition") :: (base / "other") :: (base / "type") :: Nil }, + sourceGenerators in Compile <+= (cacheDirectory, apiDefinitions, fullClasspath in Compile in datatypeProj, sourceManaged in Compile, mainClass in datatypeProj in Compile, runner, streams) map generateAPICached + ) + +// defines operations on the API of a source, including determining whether it has changed and converting it to a string +// and discovery of Projclasses and annotations +lazy val apiProj = (project in compilePath / "api"). + dependsOn(interfaceProj). + settings(testedBaseSettings: _*). + settings( + name := "API" + ) + +/* **** Utilities **** */ + +lazy val controlProj = (project in utilPath / "control"). + settings(baseSettings ++ Util.crossBuild: _*). + settings( + name := "Control", + crossScalaVersions := Seq(scala210, scala211) + ) + +lazy val collectionProj = (project in utilPath / "collection"). + settings(testedBaseSettings ++ Util.keywordsSettings ++ Util.crossBuild: _*). + settings( + name := "Collections", + crossScalaVersions := Seq(scala210, scala211) + ) + +lazy val applyMacroProj = (project in utilPath / "appmacro"). + dependsOn(collectionProj). + settings(testedBaseSettings: _*). + settings( + name := "Apply Macro", + libraryDependencies += scalaCompiler.value + ) + +// The API for forking, combining, and doing I/O with system processes +lazy val processProj = (project in utilPath / "process"). + dependsOn(ioProj % "test->test"). + settings(baseSettings: _*). + settings( + name := "Process", + libraryDependencies ++= scalaXml.value + ) + +// Path, IO (formerly FileUtilities), NameFilter and other I/O utility classes +lazy val ioProj = (project in utilPath / "io"). + dependsOn(controlProj). + settings(testedBaseSettings ++ Util.crossBuild: _*). + settings( + name := "IO", + libraryDependencies += scalaCompiler.value % Test, + crossScalaVersions := Seq(scala210, scala211) + ) + +// Utilities related to reflection, managing Scala versions, and custom class loaders +lazy val classpathProj = (project in utilPath / "classpath"). + dependsOn(launchInterfaceProj, interfaceProj, ioProj). + settings(testedBaseSettings: _*). + settings( + name := "Classpath", + libraryDependencies += scalaCompiler.value + ) + +// Command line-related utilities. +lazy val completeProj = (project in utilPath / "complete"). + dependsOn(collectionProj, controlProj, ioProj). + settings(testedBaseSettings ++ Util.crossBuild: _*). + settings( + name := "Completion", + libraryDependencies += jline, + crossScalaVersions := Seq(scala210, scala211) + ) + +// logging +lazy val logProj = (project in utilPath / "log"). + dependsOn(interfaceProj, processProj). + settings(testedBaseSettings: _*). + settings( + name := "Logging", + libraryDependencies += jline + ) + +// Relation +lazy val relationProj = (project in utilPath / "relation"). + dependsOn(interfaceProj, processProj). + settings(testedBaseSettings: _*). + settings( + name := "Relation" + ) + +// class file reader and analyzer +lazy val classfileProj = (project in utilPath / "classfile"). + dependsOn(ioProj, interfaceProj, logProj). + settings(testedBaseSettings: _*). + settings( + name := "Classfile" + ) + +// generates immutable or mutable Java data types according to a simple input format +lazy val datatypeProj = (project in utilPath / "datatype"). + dependsOn(ioProj). + settings(baseSettings: _*). + settings( + name := "Datatype Generator" + ) + +// cross versioning +lazy val crossProj = (project in utilPath / "cross"). + settings(baseSettings: _*). + settings(inConfig(Compile)(Transform.crossGenSettings): _*). + settings( + name := "Cross" + ) + +// A logic with restricted negation as failure for a unique, stable model +lazy val logicProj = (project in utilPath / "logic"). + dependsOn(collectionProj, relationProj). + settings(testedBaseSettings: _*). + settings( + name := "Logic" + ) + +/* **** Intermediate-level Modules **** */ + +// Apache Ivy integration +lazy val ivyProj = (project in file("ivy")). + dependsOn(interfaceProj, launchInterfaceProj, crossProj, logProj % "compile;test->test", ioProj % "compile;test->test", launchProj % "test->test", collectionProj). + settings(baseSettings: _*). + settings( + name := "Ivy", + libraryDependencies ++= Seq(ivy, jsch, json4sNative, jawnParser, jawnJson4s), + testExclusive) + +// Runner for uniform test interface +lazy val testingProj = (project in file("testing")). + dependsOn(ioProj, classpathProj, logProj, launchInterfaceProj, testAgentProj). + settings(baseSettings: _*). + settings( + name := "Testing", + libraryDependencies += testInterface + ) + +// Testing agent for running tests in a separate process. +lazy val testAgentProj = (project in file("testing") / "agent"). + settings(minimalSettings: _*). + settings( + name := "Test Agent", + libraryDependencies += testInterface + ) + +// Basic task engine +lazy val taskProj = (project in tasksPath). + dependsOn(controlProj, collectionProj). + settings(testedBaseSettings: _*). + settings( + name := "Tasks" + ) + +// Standard task system. This provides map, flatMap, join, and more on top of the basic task model. +lazy val stdTaskProj = (project in tasksPath / "standard"). + dependsOn (taskProj % "compile;test->test", collectionProj, logProj, ioProj, processProj). + settings(testedBaseSettings: _*). + settings( + name := "Task System", + testExclusive + ) + +// Persisted caching based on SBinary +lazy val cacheProj = (project in cachePath). + dependsOn (ioProj, collectionProj). + settings(baseSettings: _*). + settings( + name := "Cache", + libraryDependencies ++= Seq(sbinary) ++ scalaXml.value + ) + +// Builds on cache to provide caching for filesystem-related operations +lazy val trackingProj = (project in cachePath / "tracking"). + dependsOn(cacheProj, ioProj). + settings(baseSettings: _*). + settings( + name := "Tracking" + ) + +// Embedded Scala code runner +lazy val runProj = (project in file("run")). + dependsOn (ioProj, logProj % "compile;test->test", classpathProj, processProj % "compile;test->test"). + settings(testedBaseSettings: _*). + settings( + name := "Run" + ) + +// Compiler-side interface to compiler that is compiled against the compiler being used either in advance or on the fly. +// Includes API and Analyzer phases that extract source API and relationships. +lazy val compileInterfaceProj = (project in compilePath / "interface"). + dependsOn(interfaceProj % "compile;test->test", ioProj % "test->test", logProj % "test->test", launchProj % "test->test", apiProj % "test->test"). + settings(baseSettings ++ precompiledSettings: _*). + settings( + name := "Compiler Interface", + exportJars := true, + // we need to fork because in unit tests we set usejavacp = true which means + // we are expecting all of our dependencies to be on classpath so Scala compiler + // can use them while constructing its own classpath for compilation + fork in Test := true, + // needed because we fork tests and tests are ran in parallel so we have multiple Scala + // compiler instances that are memory hungry + javaOptions in Test += "-Xmx1G", + artifact in (Compile, packageSrc) := Artifact(srcID).copy(configurations = Compile :: Nil).extra("e:component" -> srcID) + ) + +lazy val precompiled282 = precompiled("2.8.2") +lazy val precompiled292 = precompiled("2.9.2") +lazy val precompiled293 = precompiled("2.9.3") + +// Implements the core functionality of detecting and propagating changes incrementally. +// Defines the data structures for representing file fingerprints and relationships and the overall source analysis +lazy val compileIncrementalProj = (project in compilePath / "inc"). + dependsOn (apiProj, ioProj, logProj, classpathProj, relationProj). + settings(testedBaseSettings: _*). + settings( + name := "Incremental Compiler" + ) + +// Persists the incremental data structures using SBinary +lazy val compilePersistProj = (project in compilePath / "persist"). + dependsOn(compileIncrementalProj, apiProj, compileIncrementalProj % "test->test"). + settings(testedBaseSettings: _*). + settings( + name := "Persist", + libraryDependencies += sbinary + ) + +// sbt-side interface to compiler. Calls compiler-side interface reflectively +lazy val compilerProj = (project in compilePath). + dependsOn(launchInterfaceProj, interfaceProj % "compile;test->test", logProj, ioProj, classpathProj, apiProj, classfileProj, + logProj % "test->test", launchProj % "test->test"). + settings(testedBaseSettings: _*). + settings( + name := "Compile", + libraryDependencies += scalaCompiler.value % Test, + unmanagedJars in Test <<= (packageSrc in compileInterfaceProj in Compile).map(x => Seq(x).classpath) + ) + +lazy val compilerIntegrationProj = (project in (compilePath / "integration")). + dependsOn(compileIncrementalProj, compilerProj, compilePersistProj, apiProj, classfileProj). + settings(baseSettings: _*). + settings( + name := "Compiler Integration" + ) + +lazy val compilerIvyProj = (project in compilePath / "ivy"). + dependsOn (ivyProj, compilerProj). + settings(baseSettings: _*). + settings( + name := "Compiler Ivy Integration" + ) + +lazy val scriptedBaseProj = (project in scriptedPath / "base"). + dependsOn (ioProj, processProj). + settings(testedBaseSettings: _*). + settings( + name := "Scripted Framework", + libraryDependencies ++= scalaParsers.value + ) + +lazy val scriptedSbtProj = (project in scriptedPath / "sbt"). + dependsOn (ioProj, logProj, processProj, scriptedBaseProj, launchInterfaceProj % "provided"). + settings(baseSettings: _*). + settings( + name := "Scripted sbt" + ) + +lazy val scriptedPluginProj = (project in scriptedPath / "plugin"). + dependsOn (sbtProj, classpathProj). + settings(baseSettings: _*). + settings( + name := "Scripted Plugin" + ) + +// Implementation and support code for defining actions. +lazy val actionsProj = (project in mainPath / "actions"). + dependsOn (classpathProj, completeProj, apiProj, compilerIntegrationProj, compilerIvyProj, + interfaceProj, ioProj, ivyProj, logProj, processProj, runProj, relationProj, stdTaskProj, + taskProj, trackingProj, testingProj). + settings(testedBaseSettings: _*). + settings( + name := "Actions" + ) + +// General command support and core commands not specific to a build system +lazy val commandProj = (project in mainPath / "command"). + dependsOn(interfaceProj, ioProj, launchInterfaceProj, logProj, completeProj, classpathProj, crossProj). + settings(testedBaseSettings: _*). + settings( + name := "Command" + ) + +// Fixes scope=Scope for Setting (core defined in collectionProj) to define the settings system used in build definitions +lazy val mainSettingsProj = (project in mainPath / "settings"). + dependsOn (applyMacroProj, interfaceProj, ivyProj, relationProj, logProj, ioProj, commandProj, + completeProj, classpathProj, stdTaskProj, processProj). + settings(testedBaseSettings: _*). + settings( + name := "Main Settings", + libraryDependencies += sbinary + ) + +// The main integration project for sbt. It brings all of the Projsystems together, configures them, and provides for overriding conventions. +lazy val mainProj = (project in mainPath). + dependsOn (actionsProj, mainSettingsProj, interfaceProj, ioProj, ivyProj, launchInterfaceProj, logProj, logicProj, processProj, runProj, commandProj). + settings(testedBaseSettings: _*). + settings( + name := "Main", + libraryDependencies ++= scalaXml.value + ) + +// Strictly for bringing implicits and aliases from subsystems into the top-level sbt namespace through a single package object +// technically, we need a dependency on all of mainProj's dependencies, but we don't do that since this is strictly an integration project +// with the sole purpose of providing certain identifiers without qualification (with a package object) +lazy val sbtProj = (project in sbtPath). + dependsOn(mainProj, compileInterfaceProj, precompiled282, precompiled292, precompiled293, scriptedSbtProj % "test->test"). + settings(baseSettings: _*). + settings( + name := "sbt", + normalizedName := "sbt" + ) + +def scriptedTask: Initialize[InputTask[Unit]] = InputTask(scriptedSource(dir => (s: State) => scriptedParser(dir))) { result => + (proguard in Proguard, fullClasspath in scriptedSbtProj in Test, scalaInstance in scriptedSbtProj, publishAll, scriptedSource, result) map { + (launcher, scriptedSbtClasspath, scriptedSbtInstance, _, sourcePath, args) => + doScripted(launcher, scriptedSbtClasspath, scriptedSbtInstance, sourcePath, args) + } +} + +def scriptedUnpublishedTask: Initialize[InputTask[Unit]] = InputTask(scriptedSource(dir => (s: State) => scriptedParser(dir))) { result => + (proguard in Proguard, fullClasspath in scriptedSbtProj in Test, scalaInstance in scriptedSbtProj, scriptedSource, result) map doScripted +} + +lazy val publishAll = TaskKey[Unit]("publish-all") +lazy val publishLauncher = TaskKey[Unit]("publish-launcher") + +lazy val myProvided = config("provided") intransitive + +def allProjects = Seq(launchInterfaceProj, launchProj, testSamples, interfaceProj, apiProj, + controlProj, collectionProj, applyMacroProj, processProj, ioProj, classpathProj, completeProj, + logProj, relationProj, classfileProj, datatypeProj, crossProj, logicProj, ivyProj, + testingProj, testAgentProj, taskProj, stdTaskProj, cacheProj, trackingProj, runProj, + compileInterfaceProj, compileIncrementalProj, compilePersistProj, compilerProj, + compilerIntegrationProj, compilerIvyProj, + scriptedBaseProj, scriptedSbtProj, scriptedPluginProj, + actionsProj, commandProj, mainSettingsProj, mainProj, sbtProj) +def projectsWithMyProvided = allProjects.map(p => p.copy(configurations = (p.configurations.filter(_ != Provided)) :+ myProvided)) +lazy val nonRoots = projectsWithMyProvided.map(p => LocalProject(p.id)) + +def releaseSettings = Release.settings(nonRoots, proguard in Proguard) +def rootSettings = releaseSettings ++ fullDocSettings ++ LaunchProguard.settings ++ LaunchProguard.specific(launchProj) ++ + Util.publishPomSettings ++ otherRootSettings ++ proguardedLauncherSettings ++ Formatting.sbtFilesSettings ++ + Transform.conscriptSettings(launchProj) +def otherRootSettings = Seq( + Scripted.scripted <<= scriptedTask, + Scripted.scriptedUnpublished <<= scriptedUnpublishedTask, + Scripted.scriptedSource <<= (sourceDirectory in sbtProj) / "sbt-test", + publishAll := { + (publishLocal).all(ScopeFilter(inAnyProject)).value + } +) +lazy val docProjects: ScopeFilter = ScopeFilter( + inAnyProject -- inProjects(root, sbtProj, scriptedBaseProj, scriptedSbtProj, scriptedPluginProj), + inConfigurations(Compile) +) +def fullDocSettings = Util.baseScalacOptions ++ Docs.settings ++ Sxr.settings ++ Seq( + scalacOptions += "-Ymacro-no-expand", // for both sxr and doc + sources in sxr := { + val allSources = (sources ?? Nil).all(docProjects).value + allSources.flatten.distinct + }, //sxr + sources in (Compile, doc) := (sources in sxr).value, // doc + Sxr.sourceDirectories := { + val allSourceDirectories = (sourceDirectories ?? Nil).all(docProjects).value + allSourceDirectories.flatten + }, + fullClasspath in sxr := (externalDependencyClasspath in Compile in sbtProj).value, + dependencyClasspath in (Compile, doc) := (fullClasspath in sxr).value +) + +// the launcher is published with metadata so that the scripted plugin can pull it in +// being proguarded, it shouldn't ever be on a classpath with other jars, however +def proguardedLauncherSettings = Seq( + publishArtifact in packageSrc := false, + moduleName := "sbt-launch", + autoScalaLibrary := false, + description := "sbt application launcher", + publishLauncher <<= Release.deployLauncher, + packageBin in Compile <<= proguard in Proguard +) + +/* Nested Projproject paths */ +def sbtPath = file("sbt") +def cachePath = file("cache") +def tasksPath = file("tasks") +def launchPath = file("launch") +def utilPath = file("util") +def compilePath = file("compile") +def mainPath = file("main") + +def precompiledSettings = Seq( + artifact in packageBin <<= (appConfiguration, scalaVersion) { (app, sv) => + val launcher = app.provider.scalaProvider.launcher + val bincID = binID + "_" + ScalaInstance(sv, launcher).actualVersion + Artifact(binID) extra ("e:component" -> bincID) + }, + target <<= (target, scalaVersion) { (base, sv) => base / ("precompiled_" + sv) }, + scalacOptions := Nil, + ivyScala ~= { _.map(_.copy(checkExplicit = false, overrideScalaVersion = false)) }, + exportedProducts in Compile := Nil, + libraryDependencies += scalaCompiler.value % "provided" +) + +def precompiled(scalav: String): Project = Project(id = normalize("Precompiled " + scalav.replace('.', '_')), base = compilePath / "interface"). + dependsOn(interfaceProj). + settings(baseSettings ++ precompiledSettings: _*). + settings( + name := "Precompiled " + scalav.replace('.', '_'), + scalaHome := None, + scalaVersion <<= (scalaVersion in ThisBuild) { sbtScalaV => + assert(sbtScalaV != scalav, "Precompiled compiler interface cannot have the same Scala version (" + scalav + ") as sbt.") + scalav + }, + // we disable compiling and running tests in precompiled Projprojects of compiler interface + // so we do not need to worry about cross-versioning testing dependencies + sources in Test := Nil + ) + +lazy val safeUnitTests = taskKey[Unit]("Known working tests (for both 2.10 and 2.11)") +lazy val safeProjects: ScopeFilter = ScopeFilter( + inProjects(launchProj, mainSettingsProj, mainProj, ivyProj, completeProj, + actionsProj, classpathProj, collectionProj, compileIncrementalProj, + logProj, runProj, stdTaskProj), + inConfigurations(Test) +) + +def customCommands: Seq[Setting[_]] = Seq( + commands += Command.command("setupBuildScala211") { state => + s"""set scalaVersion in ThisBuild := "$scala211" """ :: + state + }, + // This is invoked by Travis + commands += Command.command("checkBuildScala211") { state => + s"++ $scala211" :: + // First compile everything before attempting to test + "all compile test:compile" :: + // Now run known working tests. + safeUnitTests.key.label :: + state + }, + safeUnitTests := { + test.all(safeProjects).value + }, + commands += Command.command("release-sbt-local") { state => + "clean" :: + "so compile" :: + "so publishLocal" :: + "reload" :: + state + }, + commands += Command.command("release-sbt") { state => + // TODO - Any sort of validation + "clean" :: + "checkCredentials" :: + "conscript-configs" :: + "so compile" :: + "so publishSigned" :: + "publishLauncher" :: + "release-libs-211" :: + state + } +) diff --git a/project/Dependencies.scala b/project/Dependencies.scala new file mode 100644 index 000000000..887324c4f --- /dev/null +++ b/project/Dependencies.scala @@ -0,0 +1,30 @@ +import sbt._ +import Keys._ + +object Dependencies { + lazy val scala210 = "2.10.4" + lazy val scala211 = "2.11.1" + + lazy val jline = "jline" % "jline" % "2.11" + lazy val ivy = "org.scala-sbt.ivy" % "ivy" % "2.3.0-sbt-fccfbd44c9f64523b61398a0155784dcbaeae28f" + lazy val jsch = "com.jcraft" % "jsch" % "0.1.46" intransitive () + lazy val sbinary = "org.scala-tools.sbinary" %% "sbinary" % "0.4.2" + lazy val json4sNative = "org.json4s" %% "json4s-native" % "3.2.10" + lazy val jawnParser = "org.spire-math" %% "jawn-parser" % "0.6.0" + lazy val jawnJson4s = "org.spire-math" %% "json4s-support" % "0.6.0" + lazy val scalaCompiler = Def.setting { "org.scala-lang" % "scala-compiler" % scalaVersion.value } + lazy val testInterface = "org.scala-sbt" % "test-interface" % "1.0" + lazy val scalaCheck = "org.scalacheck" %% "scalacheck" % "1.11.4" + lazy val specs2 = "org.specs2" %% "specs2" % "2.3.11" + lazy val junit = "junit" % "junit" % "4.11" + + private def scala211Module(name: String, moduleVersion: String) = + Def.setting { + scalaVersion.value match { + case sv if (sv startsWith "2.9.") || (sv startsWith "2.10.") => Nil + case _ => ("org.scala-lang.modules" %% name % moduleVersion) :: Nil + } + } + lazy val scalaXml = scala211Module("scala-xml", "1.0.1") + lazy val scalaParsers = scala211Module("scala-parser-combinators", "1.0.1") +} diff --git a/project/NightlyPlugin.scala b/project/NightlyPlugin.scala new file mode 100644 index 000000000..bddc7cafc --- /dev/null +++ b/project/NightlyPlugin.scala @@ -0,0 +1,41 @@ +import sbt._ +import Keys._ +import Dependencies._ + +object NightlyPlugin extends AutoPlugin { + import autoImport._ + + override def trigger = allRequirements + override def requires = plugins.JvmPlugin + object autoImport { + lazy val nightly212 = SettingKey[Boolean]("nightly212") + lazy val includeTestDependencies = SettingKey[Boolean]("includeTestDependencies", "Doesn't declare test dependencies.") + + def testDependencies = libraryDependencies <++= includeTestDependencies { incl => + if (incl) Seq( + scalaCheck % Test, + specs2 % Test, + junit % Test + ) + else Seq() + } + } + + override def buildSettings: Seq[Setting[_]] = Seq( + nightly212 <<= scalaVersion(v => v.startsWith("2.12.")), + includeTestDependencies <<= nightly212(x => !x) + ) + + override def projectSettings: Seq[Setting[_]] = Seq( + crossVersion in update := { + scalaVersion.value match { + case sv if sv startsWith "2.8." => crossVersion.value + case sv if sv startsWith "2.9." => crossVersion.value + case sv if sv startsWith "2.10." => crossVersion.value + case sv if sv startsWith "2.11." => CrossVersion.full + case sv if sv startsWith "2.12." => CrossVersion.full + } + }, + resolvers += Resolver.typesafeIvyRepo("releases") + ) +} diff --git a/project/Sbt.scala b/project/Sbt.scala deleted file mode 100644 index 77712268a..000000000 --- a/project/Sbt.scala +++ /dev/null @@ -1,373 +0,0 @@ -// TODO(low): proper generated API sources caching: doesn't detect output directory change - -import sbt._ -import Keys._ -import Project.Initialize -import Util._ -import Common._ -import Licensed._ -import Scope.ThisScope -import LaunchProguard.{ proguard, Proguard } - -object Sbt extends Build { - override lazy val settings = super.settings ++ buildSettings ++ Status.settings ++ nightlySettings - - // Aggregate task for 2.11 - private def lameAgregateTask(task: String): String = - s"all control/$task collections/$task io/$task completion/$task" - def buildSettings = Seq( - organization := "org.scala-sbt", - version := "0.13.8-SNAPSHOT", - publishArtifact in packageDoc := false, - scalaVersion := "2.10.4", - publishMavenStyle := false, - componentID := None, - crossPaths := false, - resolvers += Resolver.typesafeIvyRepo("releases"), - concurrentRestrictions in Global += Util.testExclusiveRestriction, - testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-w", "1"), - javacOptions in compile ++= Seq("-target", "6", "-source", "6", "-Xlint", "-Xlint:-serial"), - incOptions := incOptions.value.withNameHashing(true), - commands += Command.command("setupBuildScala211") { state => - """set scalaVersion in ThisBuild := "2.11.1" """ :: - "set Util.includeTestDependencies in ThisBuild := true" :: - state - }, - commands += Command.command("checkBuildScala211") { state => - "setupBuildScala211" :: - // First compile everything before attempting to test - "all compile test:compile" :: - // Now run known working tests. - "safeUnitTests" :: - state - }, - commands += Command.command("safeUnitTests") { state => - "all launcher/test main-settings/test main/test ivy/test logic/test completion/test actions/test classpath/test collections/test incremental-compiler/test logging/test run/test task-system/test" :: - state - }, - // TODO - To some extent these should take args to figure out what to do. - commands += Command.command("release-libs-211") { state => - "setupBuildScala211" :: - /// First test - lameAgregateTask("test") :: - // Note: You need the sbt-pgp plugin installed to release. - lameAgregateTask("publishSigned") :: - // Now restore the defaults. - "reload" :: state - }, - commands += Command.command("release-sbt-local") { state => - "publishLocal" :: - "setupBuildScala211" :: - lameAgregateTask("publishLocal") :: - "reload" :: - state - }, - commands += Command.command("release-sbt") { state => - // TODO - Any sort of validation - "checkCredentials" :: - "conscript-configs" :: - "publishSigned" :: - "publishLauncher" :: - "release-libs-211" :: - state - } - ) - - lazy val myProvided = config("provided") intransitive; - override def projects = super.projects.map(p => p.copy(configurations = (p.configurations.filter(_ != Provided)) :+ myProvided)) - lazy val root: Project = Project("root", file("."), aggregate = nonRoots) settings (rootSettings: _*) configs (Sxr.sxrConf, Proguard) - lazy val nonRoots = projects.filter(_ != root).map(p => LocalProject(p.id)) - - /* ** Subproject declarations ** */ - - // defines the Java interfaces through which the launcher and the launched application communicate - lazy val launchInterfaceSub = minProject(launchPath / "interface", "Launcher Interface") settings (javaOnly: _*) - // the launcher. Retrieves, loads, and runs applications based on a configuration file. - lazy val launchSub = testedBaseProject(launchPath, "Launcher") dependsOn (ioSub % "test->test", interfaceSub % "test", launchInterfaceSub) settings (launchSettings: _*) - - // used to test the retrieving and loading of an application: sample app is packaged and published to the local repository - lazy val testSamples = noPublish(baseProject(launchPath / "test-sample", "Launch Test")) dependsOn (interfaceSub, launchInterfaceSub) settings (scalaCompiler) - - // defines Java structures used across Scala versions, such as the API structures and relationships extracted by - // the analysis compiler phases and passed back to sbt. The API structures are defined in a simple - // format from which Java sources are generated by the datatype generator subproject - lazy val interfaceSub = minProject(file("interface"), "Interface") settings (interfaceSettings: _*) - - // defines operations on the API of a source, including determining whether it has changed and converting it to a string - // and discovery of subclasses and annotations - lazy val apiSub = testedBaseProject(compilePath / "api", "API") dependsOn (interfaceSub) - - /* **** Utilities **** */ - - lazy val controlSub = baseProject(utilPath / "control", "Control") settings (Util.crossBuild: _*) - lazy val collectionSub = testedBaseProject(utilPath / "collection", "Collections") settings (Util.keywordsSettings: _*) settings (Util.crossBuild: _*) - lazy val applyMacroSub = testedBaseProject(utilPath / "appmacro", "Apply Macro") dependsOn (collectionSub) settings (scalaCompiler) - // The API for forking, combining, and doing I/O with system processes - lazy val processSub = baseProject(utilPath / "process", "Process") dependsOn (ioSub % "test->test") settings (scalaXml) - // Path, IO (formerly FileUtilities), NameFilter and other I/O utility classes - lazy val ioSub = testedBaseProject(utilPath / "io", "IO") dependsOn (controlSub) settings (ioSettings: _*) settings (Util.crossBuild: _*) - // Utilities related to reflection, managing Scala versions, and custom class loaders - lazy val classpathSub = testedBaseProject(utilPath / "classpath", "Classpath") dependsOn (launchInterfaceSub, interfaceSub, ioSub) settings (scalaCompiler) - // Command line-related utilities. - lazy val completeSub = testedBaseProject(utilPath / "complete", "Completion") dependsOn (collectionSub, controlSub, ioSub) settings (jline) settings (Util.crossBuild: _*) - // logging - lazy val logSub = testedBaseProject(utilPath / "log", "Logging") dependsOn (interfaceSub, processSub) settings (jline) - // Relation - lazy val relationSub = testedBaseProject(utilPath / "relation", "Relation") dependsOn (interfaceSub, processSub) - // class file reader and analyzer - lazy val classfileSub = testedBaseProject(utilPath / "classfile", "Classfile") dependsOn (ioSub, interfaceSub, logSub) - // generates immutable or mutable Java data types according to a simple input format - lazy val datatypeSub = baseProject(utilPath / "datatype", "Datatype Generator") dependsOn (ioSub) - // cross versioning - lazy val crossSub = baseProject(utilPath / "cross", "Cross") settings (inConfig(Compile)(Transform.crossGenSettings): _*) - // A logic with restricted negation as failure for a unique, stable model - lazy val logicSub = testedBaseProject(utilPath / "logic", "Logic").dependsOn(collectionSub, relationSub) - - /* **** Intermediate-level Modules **** */ - - // Apache Ivy integration - lazy val ivySub = baseProject(file("ivy"), "Ivy") dependsOn (interfaceSub, launchInterfaceSub, crossSub, logSub % "compile;test->test", ioSub % "compile;test->test", launchSub % "test->test", collectionSub) settings (ivy, jsch, testExclusive, json4sNative, jawnParser, jawnJson4s) - // Runner for uniform test interface - lazy val testingSub = baseProject(file("testing"), "Testing") dependsOn (ioSub, classpathSub, logSub, launchInterfaceSub, testAgentSub) settings (testInterface) - // Testing agent for running tests in a separate process. - lazy val testAgentSub = minProject(file("testing/agent"), "Test Agent") settings (testInterface) - - // Basic task engine - lazy val taskSub = testedBaseProject(tasksPath, "Tasks") dependsOn (controlSub, collectionSub) - // Standard task system. This provides map, flatMap, join, and more on top of the basic task model. - lazy val stdTaskSub = testedBaseProject(tasksPath / "standard", "Task System") dependsOn (taskSub % "compile;test->test", collectionSub, logSub, ioSub, processSub) settings (testExclusive) - // Persisted caching based on SBinary - lazy val cacheSub = baseProject(cachePath, "Cache") dependsOn (ioSub, collectionSub) settings (sbinary, scalaXml) - // Builds on cache to provide caching for filesystem-related operations - lazy val trackingSub = baseProject(cachePath / "tracking", "Tracking") dependsOn (cacheSub, ioSub) - // Embedded Scala code runner - lazy val runSub = testedBaseProject(file("run"), "Run") dependsOn (ioSub, logSub % "compile;test->test", classpathSub, processSub % "compile;test->test") - - // Compiler-side interface to compiler that is compiled against the compiler being used either in advance or on the fly. - // Includes API and Analyzer phases that extract source API and relationships. - lazy val compileInterfaceSub = baseProject(compilePath / "interface", "Compiler Interface") dependsOn (interfaceSub % "compile;test->test", ioSub % "test->test", logSub % "test->test", launchSub % "test->test", apiSub % "test->test") settings (compileInterfaceSettings: _*) - lazy val precompiled282 = precompiled("2.8.2") - lazy val precompiled292 = precompiled("2.9.2") - lazy val precompiled293 = precompiled("2.9.3") - - // Implements the core functionality of detecting and propagating changes incrementally. - // Defines the data structures for representing file fingerprints and relationships and the overall source analysis - lazy val compileIncrementalSub = testedBaseProject(compilePath / "inc", "Incremental Compiler") dependsOn (apiSub, ioSub, logSub, classpathSub, relationSub) - // Persists the incremental data structures using SBinary - lazy val compilePersistSub = testedBaseProject(compilePath / "persist", "Persist") dependsOn (compileIncrementalSub, apiSub, compileIncrementalSub % "test->test") settings (sbinary) - // sbt-side interface to compiler. Calls compiler-side interface reflectively - lazy val compilerSub = testedBaseProject(compilePath, "Compile") dependsOn (launchInterfaceSub, interfaceSub % "compile;test->test", logSub, ioSub, classpathSub, apiSub, classfileSub, - logSub % "test->test", launchSub % "test->test") settings (compilerSettings: _*) - lazy val compilerIntegrationSub = baseProject(compilePath / "integration", "Compiler Integration") dependsOn ( - compileIncrementalSub, compilerSub, compilePersistSub, apiSub, classfileSub) - lazy val compilerIvySub = baseProject(compilePath / "ivy", "Compiler Ivy Integration") dependsOn (ivySub, compilerSub) - - lazy val scriptedBaseSub = testedBaseProject(scriptedPath / "base", "Scripted Framework") dependsOn (ioSub, processSub) settings (scalaParsers) - lazy val scriptedSbtSub = baseProject(scriptedPath / "sbt", "Scripted sbt") dependsOn (ioSub, logSub, processSub, scriptedBaseSub, launchInterfaceSub % "provided") - lazy val scriptedPluginSub = baseProject(scriptedPath / "plugin", "Scripted Plugin") dependsOn (sbtSub, classpathSub) - - // Implementation and support code for defining actions. - lazy val actionsSub = testedBaseProject(mainPath / "actions", "Actions") dependsOn ( - classpathSub, completeSub, apiSub, compilerIntegrationSub, compilerIvySub, - interfaceSub, ioSub, ivySub, logSub, processSub, runSub, relationSub, stdTaskSub, taskSub, trackingSub, testingSub) - - // General command support and core commands not specific to a build system - lazy val commandSub = testedBaseProject(mainPath / "command", "Command") dependsOn (interfaceSub, ioSub, launchInterfaceSub, logSub, completeSub, classpathSub, crossSub) - // Fixes scope=Scope for Setting (core defined in collectionSub) to define the settings system used in build definitions - lazy val mainSettingsSub = testedBaseProject(mainPath / "settings", "Main Settings") dependsOn (applyMacroSub, interfaceSub, ivySub, relationSub, logSub, ioSub, commandSub, - completeSub, classpathSub, stdTaskSub, processSub) settings (sbinary) - - // The main integration project for sbt. It brings all of the subsystems together, configures them, and provides for overriding conventions. - lazy val mainSub = testedBaseProject(mainPath, "Main") dependsOn (actionsSub, mainSettingsSub, interfaceSub, ioSub, ivySub, launchInterfaceSub, logSub, logicSub, processSub, runSub, commandSub) settings (scalaXml) - - // Strictly for bringing implicits and aliases from subsystems into the top-level sbt namespace through a single package object - // technically, we need a dependency on all of mainSub's dependencies, but we don't do that since this is strictly an integration project - // with the sole purpose of providing certain identifiers without qualification (with a package object) - lazy val sbtSub = baseProject(sbtPath, "sbt") dependsOn (mainSub, compileInterfaceSub, precompiled282, precompiled292, precompiled293, scriptedSbtSub % "test->test") settings (sbtSettings: _*) - - /* Nested subproject paths */ - def sbtPath = file("sbt") - def cachePath = file("cache") - def tasksPath = file("tasks") - def launchPath = file("launch") - def utilPath = file("util") - def compilePath = file("compile") - def mainPath = file("main") - def scriptedPath = file("scripted") - - def sbtSettings = Seq( - normalizedName := "sbt" - ) - - private def doScripted(launcher: File, scriptedSbtClasspath: Seq[Attributed[File]], scriptedSbtInstance: ScalaInstance, sourcePath: File, args: Seq[String]) { - System.err.println(s"About to run tests: ${args.mkString("\n * ", "\n * ", "\n")}") - val noJLine = new classpath.FilteredLoader(scriptedSbtInstance.loader, "jline." :: Nil) - val loader = classpath.ClasspathUtilities.toLoader(scriptedSbtClasspath.files, noJLine) - val m = ModuleUtilities.getObject("sbt.test.ScriptedTests", loader) - val r = m.getClass.getMethod("run", classOf[File], classOf[Boolean], classOf[Array[String]], classOf[File], classOf[Array[String]]) - val launcherVmOptions = Array("-XX:MaxPermSize=256M") // increased after a failure in scripted source-dependencies/macro - try { r.invoke(m, sourcePath, true: java.lang.Boolean, args.toArray[String], launcher, launcherVmOptions) } - catch { case ite: java.lang.reflect.InvocationTargetException => throw ite.getCause } - } - - def scriptedTask: Initialize[InputTask[Unit]] = InputTask(scriptedSource(dir => (s: State) => scriptedParser(dir))) { result => - (proguard in Proguard, fullClasspath in scriptedSbtSub in Test, scalaInstance in scriptedSbtSub, publishAll, scriptedSource, result) map { - (launcher, scriptedSbtClasspath, scriptedSbtInstance, _, sourcePath, args) => - doScripted(launcher, scriptedSbtClasspath, scriptedSbtInstance, sourcePath, args) - } - } - - def scriptedUnpublishedTask: Initialize[InputTask[Unit]] = InputTask(scriptedSource(dir => (s: State) => scriptedParser(dir))) { result => - (proguard in Proguard, fullClasspath in scriptedSbtSub in Test, scalaInstance in scriptedSbtSub, scriptedSource, result) map doScripted - } - - import sbt.complete._ - import DefaultParsers._ - // Paging, 1-index based. - case class ScriptedTestPage(page: Int, total: Int) - def scriptedParser(scriptedBase: File): Parser[Seq[String]] = - { - val pairs = (scriptedBase * AllPassFilter * AllPassFilter * "test").get map { (f: File) => - val p = f.getParentFile - (p.getParentFile.getName, p.getName) - }; - val pairMap = pairs.groupBy(_._1).mapValues(_.map(_._2).toSet); - - val id = charClass(c => !c.isWhitespace && c != '/').+.string - val groupP = token(id.examples(pairMap.keySet.toSet)) <~ token('/') - - // A parser for page definitions - val pageP: Parser[ScriptedTestPage] = ("*" ~ NatBasic ~ "of" ~ NatBasic) map { - case _ ~ page ~ _ ~ total => ScriptedTestPage(page, total) - } - // Grabs the filenames from a given test group in the current page definition. - def pagedFilenames(group: String, page: ScriptedTestPage): Seq[String] = { - val files = pairMap(group).toSeq.sortBy(_.toLowerCase) - val pageSize = files.size / page.total - // The last page may loose some values, so we explicitly keep them - val dropped = files.drop(pageSize * (page.page - 1)) - if (page.page == page.total) dropped - else dropped.take(pageSize) - } - def nameP(group: String) = { - token("*".id | id.examples(pairMap(group))) - } - val PagedIds: Parser[Seq[String]] = - for { - group <- groupP - page <- pageP - files = pagedFilenames(group, page) - // TODO - Fail the parser if we don't have enough files for the given page size - //if !files.isEmpty - } yield files map (f => group + '/' + f) - - val testID = (for (group <- groupP; name <- nameP(group)) yield (group, name)) - val testIdAsGroup = matched(testID) map (test => Seq(test)) - //(token(Space) ~> matched(testID)).* - (token(Space) ~> (PagedIds | testIdAsGroup)).* map (_.flatten) - } - - lazy val scripted = InputKey[Unit]("scripted") - lazy val scriptedUnpublished = InputKey[Unit]("scripted-unpublished", "Execute scripted without publishing SBT first. Saves you some time when only your test has changed.") - lazy val scriptedSource = SettingKey[File]("scripted-source") - lazy val publishAll = TaskKey[Unit]("publish-all") - lazy val publishLauncher = TaskKey[Unit]("publish-launcher") - - def deepTasks[T](scoped: TaskKey[Seq[T]]): Initialize[Task[Seq[T]]] = deep(scoped.task) { _.join.map(_.flatten.distinct) } - def deep[T](scoped: SettingKey[T]): Initialize[Seq[T]] = - Util.inAllProjects(projects filterNot Set(root, sbtSub, scriptedBaseSub, scriptedSbtSub, scriptedPluginSub) map { p => LocalProject(p.id) }, scoped) - - def launchSettings = - Seq(ivy, - compile in Test <<= compile in Test dependsOn (publishLocal in interfaceSub, publishLocal in testSamples, publishLocal in launchInterfaceSub) - ) ++ - inConfig(Compile)(Transform.configSettings) ++ - inConfig(Compile)(Transform.transSourceSettings ++ Seq( - Transform.inputSourceDirectory <<= (sourceDirectory in crossSub) / "input_sources", - Transform.sourceProperties := Map("cross.package0" -> "xsbt", "cross.package1" -> "boot") - )) - - import Sxr.sxr - def releaseSettings = Release.settings(nonRoots, proguard in Proguard) - def rootSettings = releaseSettings ++ fullDocSettings ++ LaunchProguard.settings ++ LaunchProguard.specific(launchSub) ++ - Util.publishPomSettings ++ otherRootSettings ++ proguardedLauncherSettings ++ Formatting.sbtFilesSettings ++ - Transform.conscriptSettings(launchSub) - def otherRootSettings = Seq( - scripted <<= scriptedTask, - scriptedUnpublished <<= scriptedUnpublishedTask, - scriptedSource <<= (sourceDirectory in sbtSub) / "sbt-test", - publishAll <<= inAll(nonRoots, publishLocal.task), - publishAll <<= (publishAll, publishLocal).map((x, y) => ()) // publish all normal deps as well as the sbt-launch jar - ) - def fullDocSettings = Util.baseScalacOptions ++ Docs.settings ++ Sxr.settings ++ Seq( - scalacOptions += "-Ymacro-no-expand", // for both sxr and doc - sources in sxr <<= deepTasks(sources in Compile), //sxr - sources in (Compile, doc) <<= sources in sxr, // doc - Sxr.sourceDirectories <<= deep(sourceDirectories in Compile).map(_.flatten), // to properly relativize the source paths - fullClasspath in sxr <<= (externalDependencyClasspath in Compile in sbtSub), - dependencyClasspath in (Compile, doc) <<= fullClasspath in sxr - ) - - // the launcher is published with metadata so that the scripted plugin can pull it in - // being proguarded, it shouldn't ever be on a classpath with other jars, however - def proguardedLauncherSettings = Seq( - publishArtifact in packageSrc := false, - moduleName := "sbt-launch", - autoScalaLibrary := false, - description := "sbt application launcher", - publishLauncher <<= Release.deployLauncher, - packageBin in Compile <<= proguard in Proguard - ) - - def interfaceSettings = javaOnly ++ Seq( - projectComponent, - exportJars := true, - componentID := Some("xsbti"), - watchSources <++= apiDefinitions, - resourceGenerators in Compile <+= (version, resourceManaged, streams, compile in Compile) map generateVersionFile, - apiDefinitions <<= baseDirectory map { base => (base / "definition") :: (base / "other") :: (base / "type") :: Nil }, - sourceGenerators in Compile <+= (cacheDirectory, apiDefinitions, fullClasspath in Compile in datatypeSub, sourceManaged in Compile, mainClass in datatypeSub in Compile, runner, streams) map generateAPICached - ) - - def precompiledSettings = Seq( - artifact in packageBin <<= (appConfiguration, scalaVersion) { (app, sv) => - val launcher = app.provider.scalaProvider.launcher - val bincID = binID + "_" + ScalaInstance(sv, launcher).actualVersion - Artifact(binID) extra ("e:component" -> bincID) - }, - target <<= (target, scalaVersion) { (base, sv) => base / ("precompiled_" + sv) }, - scalacOptions := Nil, - ivyScala ~= { _.map(_.copy(checkExplicit = false, overrideScalaVersion = false)) }, - exportedProducts in Compile := Nil, - libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _ % "provided") - ) - // - def compileInterfaceSettings: Seq[Setting[_]] = precompiledSettings ++ Seq[Setting[_]]( - exportJars := true, - // we need to fork because in unit tests we set usejavacp = true which means - // we are expecting all of our dependencies to be on classpath so Scala compiler - // can use them while constructing its own classpath for compilation - fork in Test := true, - // needed because we fork tests and tests are ran in parallel so we have multiple Scala - // compiler instances that are memory hungry - javaOptions in Test += "-Xmx1G", - artifact in (Compile, packageSrc) := Artifact(srcID).copy(configurations = Compile :: Nil).extra("e:component" -> srcID) - ) - def compilerSettings = Seq( - libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _ % "test"), - unmanagedJars in Test <<= (packageSrc in compileInterfaceSub in Compile).map(x => Seq(x).classpath) - ) - def precompiled(scalav: String): Project = baseProject(compilePath / "interface", "Precompiled " + scalav.replace('.', '_')) dependsOn (interfaceSub) settings (precompiledSettings: _*) settings ( - scalaHome := None, - scalaVersion <<= (scalaVersion in ThisBuild) { sbtScalaV => - assert(sbtScalaV != scalav, "Precompiled compiler interface cannot have the same Scala version (" + scalav + ") as sbt.") - scalav - }, - // we disable compiling and running tests in precompiled subprojects of compiler interface - // so we do not need to worry about cross-versioning testing dependencies - sources in Test := Nil - ) - def ioSettings: Seq[Setting[_]] = Seq( - libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _ % "test") - ) -} diff --git a/project/Scripted.scala b/project/Scripted.scala new file mode 100644 index 000000000..87eb164a8 --- /dev/null +++ b/project/Scripted.scala @@ -0,0 +1,69 @@ +import sbt._ +import Keys._ +import Def.Initialize +import LaunchProguard._ + +object Scripted { + def scriptedPath = file("scripted") + lazy val scripted = InputKey[Unit]("scripted") + lazy val scriptedUnpublished = InputKey[Unit]("scripted-unpublished", "Execute scripted without publishing SBT first. Saves you some time when only your test has changed.") + lazy val scriptedSource = SettingKey[File]("scripted-source") + + import sbt.complete._ + import DefaultParsers._ + // Paging, 1-index based. + case class ScriptedTestPage(page: Int, total: Int) + def scriptedParser(scriptedBase: File): Parser[Seq[String]] = + { + val pairs = (scriptedBase * AllPassFilter * AllPassFilter * "test").get map { (f: File) => + val p = f.getParentFile + (p.getParentFile.getName, p.getName) + }; + val pairMap = pairs.groupBy(_._1).mapValues(_.map(_._2).toSet); + + val id = charClass(c => !c.isWhitespace && c != '/').+.string + val groupP = token(id.examples(pairMap.keySet.toSet)) <~ token('/') + + // A parser for page definitions + val pageP: Parser[ScriptedTestPage] = ("*" ~ NatBasic ~ "of" ~ NatBasic) map { + case _ ~ page ~ _ ~ total => ScriptedTestPage(page, total) + } + // Grabs the filenames from a given test group in the current page definition. + def pagedFilenames(group: String, page: ScriptedTestPage): Seq[String] = { + val files = pairMap(group).toSeq.sortBy(_.toLowerCase) + val pageSize = files.size / page.total + // The last page may loose some values, so we explicitly keep them + val dropped = files.drop(pageSize * (page.page - 1)) + if (page.page == page.total) dropped + else dropped.take(pageSize) + } + def nameP(group: String) = { + token("*".id | id.examples(pairMap(group))) + } + val PagedIds: Parser[Seq[String]] = + for { + group <- groupP + page <- pageP + files = pagedFilenames(group, page) + // TODO - Fail the parser if we don't have enough files for the given page size + //if !files.isEmpty + } yield files map (f => group + '/' + f) + + val testID = (for (group <- groupP; name <- nameP(group)) yield (group, name)) + val testIdAsGroup = matched(testID) map (test => Seq(test)) + //(token(Space) ~> matched(testID)).* + (token(Space) ~> (PagedIds | testIdAsGroup)).* map (_.flatten) + } + + def doScripted(launcher: File, scriptedSbtClasspath: Seq[Attributed[File]], scriptedSbtInstance: ScalaInstance, sourcePath: File, args: Seq[String]) { + System.err.println(s"About to run tests: ${args.mkString("\n * ", "\n * ", "\n")}") + val noJLine = new classpath.FilteredLoader(scriptedSbtInstance.loader, "jline." :: Nil) + val loader = classpath.ClasspathUtilities.toLoader(scriptedSbtClasspath.files, noJLine) + val m = ModuleUtilities.getObject("sbt.test.ScriptedTests", loader) + val r = m.getClass.getMethod("run", classOf[File], classOf[Boolean], classOf[Array[String]], classOf[File], classOf[Array[String]]) + val launcherVmOptions = Array("-XX:MaxPermSize=256M") // increased after a failure in scripted source-dependencies/macro + try { r.invoke(m, sourcePath, true: java.lang.Boolean, args.toArray[String], launcher, launcherVmOptions) } + catch { case ite: java.lang.reflect.InvocationTargetException => throw ite.getCause } + } + +} \ No newline at end of file diff --git a/project/Util.scala b/project/Util.scala index 0e932a68e..6217cce8b 100644 --- a/project/Util.scala +++ b/project/Util.scala @@ -7,28 +7,9 @@ object Util { lazy val componentID = SettingKey[Option[String]]("component-id") lazy val scalaKeywords = TaskKey[Set[String]]("scala-keywords") lazy val generateKeywords = TaskKey[File]("generateKeywords") - lazy val nightly211 = SettingKey[Boolean]("nightly-211") - lazy val includeTestDependencies = SettingKey[Boolean]("includeTestDependencies", "Doesn't declare test dependencies.") - def inAll(projects: => Seq[ProjectReference], key: SettingKey[Task[Unit]]): Project.Initialize[Task[Unit]] = - inAllProjects(projects, key) { deps => nop dependsOn (deps: _*) } + def noPublishSettings: Seq[Setting[_]] = Seq(publish := {}) - def inAllProjects[T](projects: => Seq[ProjectReference], key: SettingKey[T]): Project.Initialize[Seq[T]] = - Def.settingDyn { - val lb = loadedBuild.value - val pr = thisProjectRef.value - def resolve(ref: ProjectReference): ProjectRef = Scope.resolveProjectRef(pr.build, Load.getRootProject(lb.units), ref) - val refs = projects flatMap { base => Defaults.transitiveDependencies(resolve(base.project), lb, includeRoot = true, classpath = true, aggregate = true) } - refs map (ref => (key in ref).?) joinWith (_ flatMap { x => x }) - } - - def noPublish(p: Project) = p.copy(settings = noRemotePublish(p.settings)) - def noRemotePublish(in: Seq[Setting[_]]) = in filterNot { _.key.key == publish.key } - - def nightlySettings = Seq( - nightly211 <<= scalaVersion(v => v.startsWith("2.11.") || v.startsWith("2.12.")), - includeTestDependencies <<= nightly211(x => !x) - ) def crossBuild: Seq[Setting[_]] = Seq( crossPaths := (scalaBinaryVersion.value match { @@ -36,17 +17,8 @@ object Util { case _ => false }) ) - def commonSettings(nameString: String) = Seq( - crossVersion in update <<= (crossVersion, nightly211) { (cv, n) => if (n) CrossVersion.full else cv }, - name := nameString, - resolvers += Resolver.typesafeIvyRepo("releases") - ) - def minProject(path: File, nameString: String) = Project(normalize(nameString), path) settings (commonSettings(nameString) ++ publishPomSettings ++ Release.javaVersionCheckSettings: _*) - def baseProject(path: File, nameString: String) = minProject(path, nameString) settings (base: _*) - def testedBaseProject(path: File, nameString: String) = baseProject(path, nameString) settings (testDependencies) - lazy val javaOnly = Seq[Setting[_]]( /*crossPaths := false, */ compileOrder := CompileOrder.JavaThenScala, unmanagedSourceDirectories in Compile <<= Seq(javaSource in Compile).join) - lazy val base: Seq[Setting[_]] = Seq(projectComponent) ++ baseScalacOptions ++ Licensed.settings ++ Formatting.settings + lazy val javaOnlySettings = Seq[Setting[_]]( /*crossPaths := false, */ compileOrder := CompileOrder.JavaThenScala, unmanagedSourceDirectories in Compile <<= Seq(javaSource in Compile).join) lazy val baseScalacOptions = Seq( scalacOptions ++= Seq("-Xelide-below", "0"), scalacOptions <++= scalaVersion map CrossVersion.partialVersion map { @@ -59,17 +31,6 @@ object Util { } ) - def testDependencies = libraryDependencies <++= includeTestDependencies { incl => - if (incl) Seq( - "org.scalacheck" %% "scalacheck" % "1.11.4" % "test", - "org.specs2" %% "specs2" % "2.3.11" % "test", - "junit" % "junit" % "4.11" % "test" - ) - else Seq() - } - - lazy val minimalSettings: Seq[Setting[_]] = Defaults.paths ++ Seq[Setting[_]](crossTarget := target.value, name <<= thisProject(_.id)) - def projectComponent = projectID <<= (projectID, componentID) { (pid, cid) => cid match { case Some(id) => pid extra ("e:component" -> id); case None => pid } } @@ -174,27 +135,6 @@ object %s { sourceGenerators <+= generateKeywords map (x => Seq(x)) )) } -object Common { - def lib(m: ModuleID) = libraryDependencies += m - lazy val jlineDep = "jline" % "jline" % "2.11" - lazy val jline = lib(jlineDep) - lazy val ivy = lib("org.scala-sbt.ivy" % "ivy" % "2.3.0-sbt-fccfbd44c9f64523b61398a0155784dcbaeae28f") - lazy val httpclient = lib("commons-httpclient" % "commons-httpclient" % "3.1") - lazy val jsch = lib("com.jcraft" % "jsch" % "0.1.46" intransitive ()) - lazy val sbinary = libraryDependencies += "org.scala-tools.sbinary" %% "sbinary" % "0.4.2" - lazy val json4sNative = lib("org.json4s" %% "json4s-native" % "3.2.10") - lazy val jawnParser = lib("org.spire-math" %% "jawn-parser" % "0.6.0") - lazy val jawnJson4s = lib("org.spire-math" %% "json4s-support" % "0.6.0") - lazy val scalaCompiler = libraryDependencies <+= scalaVersion(sv => "org.scala-lang" % "scala-compiler" % sv) - lazy val testInterface = lib("org.scala-sbt" % "test-interface" % "1.0") - private def scala211Module(name: String, moduleVersion: String) = - libraryDependencies <++= (scalaVersion)(scalaVersion => - if (scalaVersion.startsWith("2.11.") || scalaVersion.startsWith("2.12.")) ("org.scala-lang.modules" %% name % moduleVersion) :: Nil - else Nil - ) - lazy val scalaXml = scala211Module("scala-xml", "1.0.1") - lazy val scalaParsers = scala211Module("scala-parser-combinators", "1.0.1") -} object Licensed { lazy val notice = SettingKey[File]("notice") lazy val extractLicenses = TaskKey[Seq[File]]("extract-licenses") diff --git a/project/p.sbt b/project/p.sbt index 723e694fb..5ea1b55b1 100644 --- a/project/p.sbt +++ b/project/p.sbt @@ -12,3 +12,5 @@ addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.5.1") addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.3.0") addSbtPlugin("com.typesafe.sbt" % "sbt-javaversioncheck" % "0.1.0") + +addSbtPlugin("com.eed3si9n" % "sbt-doge" % "0.1.1")