2011-02-06 03:40:10 +01:00
|
|
|
/* sbt -- Simple Build Tool
|
|
|
|
|
* Copyright 2011 Mark Harrah
|
|
|
|
|
*/
|
2011-02-03 13:17:47 +01:00
|
|
|
package sbt
|
|
|
|
|
|
|
|
|
|
import java.io.File
|
2011-02-25 05:30:06 +01:00
|
|
|
import Build.data
|
2011-02-10 14:16:07 +01:00
|
|
|
import Scope.{GlobalScope,ThisScope}
|
2011-02-27 05:56:30 +01:00
|
|
|
import Project.{Initialize, ScopedKey, Setting}
|
2011-02-05 04:02:39 +01:00
|
|
|
import Configurations.{Compile => CompileConf, Test => TestConf}
|
2011-02-12 02:22:17 +01:00
|
|
|
import EvaluateTask.{resolvedScoped, streams}
|
|
|
|
|
import complete._
|
2011-02-03 13:17:47 +01:00
|
|
|
import std.TaskExtra._
|
|
|
|
|
import scala.xml.{Node => XNode,NodeSeq}
|
|
|
|
|
import org.apache.ivy.core.module.{descriptor, id}
|
|
|
|
|
import descriptor.ModuleDescriptor, id.ModuleRevisionId
|
2011-02-12 02:22:17 +01:00
|
|
|
import Types._
|
|
|
|
|
|
2011-02-03 13:17:47 +01:00
|
|
|
object Default
|
|
|
|
|
{
|
|
|
|
|
import Path._
|
|
|
|
|
import GlobFilter._
|
|
|
|
|
import Keys._
|
|
|
|
|
implicit def richFileSetting(s: ScopedSetting[File]): RichFileSetting = new RichFileSetting(s)
|
|
|
|
|
implicit def richFilesSetting(s: ScopedSetting[Seq[File]]): RichFilesSetting = new RichFilesSetting(s)
|
|
|
|
|
|
|
|
|
|
final class RichFileSetting(s: ScopedSetting[File]) extends RichFileBase
|
|
|
|
|
{
|
2011-02-12 02:22:17 +01:00
|
|
|
def /(c: String): Initialize[File] = s { _ / c }
|
2011-02-06 17:33:29 +01:00
|
|
|
protected[this] def map0(f: PathFinder => PathFinder) = s(file => finder(f)(file :: Nil))
|
2011-02-03 13:17:47 +01:00
|
|
|
}
|
|
|
|
|
final class RichFilesSetting(s: ScopedSetting[Seq[File]]) extends RichFileBase
|
|
|
|
|
{
|
2011-02-12 02:22:17 +01:00
|
|
|
def /(s: String): Initialize[Seq[File]] = map0 { _ / s }
|
2011-02-06 17:33:29 +01:00
|
|
|
protected[this] def map0(f: PathFinder => PathFinder) = s(finder(f))
|
2011-02-03 13:17:47 +01:00
|
|
|
}
|
|
|
|
|
sealed abstract class RichFileBase
|
|
|
|
|
{
|
2011-02-12 02:22:17 +01:00
|
|
|
def *(filter: FileFilter): Initialize[Seq[File]] = map0 { _ * filter }
|
|
|
|
|
def **(filter: FileFilter): Initialize[Seq[File]] = map0 { _ ** filter }
|
|
|
|
|
protected[this] def map0(f: PathFinder => PathFinder): Initialize[Seq[File]]
|
2011-02-03 13:17:47 +01:00
|
|
|
protected[this] def finder(f: PathFinder => PathFinder): Seq[File] => Seq[File] =
|
|
|
|
|
in => f(in).getFiles.toSeq
|
|
|
|
|
}
|
2011-02-12 02:22:17 +01:00
|
|
|
def configSrcSub(key: ScopedSetting[File]): Initialize[File] = (key, Config) { (src, conf) => src / nameForSrc(conf.name) }
|
2011-02-03 13:17:47 +01:00
|
|
|
def nameForSrc(config: String) = if(config == "compile") "main" else config
|
|
|
|
|
def prefix(config: String) = if(config == "compile") "" else config + "-"
|
2011-02-12 02:22:17 +01:00
|
|
|
def toSeq[T](key: ScopedSetting[T]): Initialize[Seq[T]] = key( _ :: Nil)
|
2011-02-03 13:17:47 +01:00
|
|
|
|
2011-02-27 05:56:30 +01:00
|
|
|
def extractAnalysis[T](a: Attributed[T]): (T, inc.Analysis) =
|
|
|
|
|
(a.data, a.metadata get Keys.Analysis getOrElse inc.Analysis.Empty)
|
2011-02-03 13:17:47 +01:00
|
|
|
|
2011-02-27 05:56:30 +01:00
|
|
|
def analysisMap[T](cp: Seq[Attributed[T]]): Map[T, inc.Analysis] =
|
2011-02-03 13:17:47 +01:00
|
|
|
(cp map extractAnalysis).toMap
|
|
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
def core: Seq[Setting[_]] = Seq(
|
|
|
|
|
JavaHome in GlobalScope :== None,
|
|
|
|
|
OutputStrategy in GlobalScope :== None,
|
|
|
|
|
Fork in GlobalScope :== false,
|
|
|
|
|
JavaOptions in GlobalScope :== Nil,
|
2011-02-21 16:22:39 +01:00
|
|
|
CrossPaths :== true,
|
2011-02-22 01:35:05 +01:00
|
|
|
ShellPrompt in GlobalScope :== (_ => "> "),
|
2011-02-21 16:07:58 +01:00
|
|
|
Aggregate in GlobalScope :== Aggregation.Enabled,
|
2011-02-16 00:41:40 +01:00
|
|
|
Name <<= ThisProject(_.id),
|
2011-02-03 13:17:47 +01:00
|
|
|
Version :== "0.1",
|
2011-02-10 14:16:07 +01:00
|
|
|
MaxErrors in GlobalScope :== 100,
|
2011-02-27 05:56:30 +01:00
|
|
|
Commands :== Nil,
|
2011-02-05 04:02:39 +01:00
|
|
|
Data <<= EvaluateTask.state map { state => Project.structure(state).data }
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
def paths = Seq(
|
2011-02-05 04:02:39 +01:00
|
|
|
Base <<= ThisProject(_.base),
|
|
|
|
|
Target <<= Base / "target",
|
2011-02-10 14:16:07 +01:00
|
|
|
DefaultExcludes in GlobalScope :== (".*" - ".") || HiddenFileFilter,
|
2011-02-05 04:02:39 +01:00
|
|
|
HistoryPath <<= Target(t => Some(t / ".history")),
|
|
|
|
|
CacheDirectory <<= Target / "cache",
|
|
|
|
|
Source <<= Base / "src",
|
2011-02-10 14:16:07 +01:00
|
|
|
SourceFilter in GlobalScope :== ("*.java" | "*.scala"),
|
2011-02-05 04:02:39 +01:00
|
|
|
SourceManaged <<= Base / "src_managed"
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
lazy val configPaths = Seq(
|
2011-02-05 04:02:39 +01:00
|
|
|
Source <<= configSrcSub( Source in Scope(This,Global,This,This) ),
|
|
|
|
|
SourceManaged <<= configSrcSub(SourceManaged),
|
|
|
|
|
CacheDirectory <<= (CacheDirectory, Config) { _ / _.name },
|
|
|
|
|
ClassDirectory <<= (Target, Config) { (target, conf) => target / (prefix(conf.name) + "classes") },
|
2011-02-06 17:33:29 +01:00
|
|
|
DocDirectory <<= (Target, Config) { (target, conf) => target / (prefix(conf.name) + "api") },
|
2011-02-05 04:02:39 +01:00
|
|
|
Sources <<= (SourceDirectories, SourceFilter, DefaultExcludes) map { (d,f,excl) => d.descendentsExcept(f,excl).getFiles.toSeq },
|
|
|
|
|
ScalaSource <<= Source / "scala",
|
|
|
|
|
JavaSource <<= Source / "java",
|
|
|
|
|
JavaSourceRoots <<= toSeq(JavaSource),
|
|
|
|
|
ResourceDir <<= Source / "resources",
|
|
|
|
|
SourceDirectories <<= (ScalaSource, JavaSourceRoots) { _ +: _ },
|
2011-02-06 19:01:50 +01:00
|
|
|
ResourceDirectories <<= toSeq(ResourceDir),
|
|
|
|
|
Resources <<= (ResourceDirectories, DefaultExcludes) map { (dirs, excl) => dirs.descendentsExcept("*",excl).getFiles.toSeq }
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
def addBaseSources = Seq(
|
2011-02-05 04:02:39 +01:00
|
|
|
Sources <<= (Sources, Base, SourceFilter, DefaultExcludes) map { (srcs,b,f,excl) => (srcs +++ b * (f -- excl)).getFiles.toSeq }
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def webPaths = Seq(
|
2011-02-05 04:02:39 +01:00
|
|
|
WebappDir <<= Source / "webapp"
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def compileBase = Seq(
|
2011-02-06 17:33:29 +01:00
|
|
|
Compilers <<= (ScalaInstance, AppConfig, streams) map { (si, app, s) => Compile.compilers(si)(app, s.log) },
|
2011-02-10 14:16:07 +01:00
|
|
|
JavacOptions in GlobalScope :== Nil,
|
|
|
|
|
ScalacOptions in GlobalScope :== Nil,
|
2011-02-09 02:34:39 +01:00
|
|
|
ScalaInstance <<= (AppConfig, ScalaVersion){ (app, version) => sbt.ScalaInstance(version, app.provider.scalaProvider.launcher) },
|
|
|
|
|
ScalaVersion <<= AppConfig( _.provider.scalaProvider.version),
|
2011-02-21 16:22:39 +01:00
|
|
|
Target <<= (Target, ScalaInstance, CrossPaths)( (t,si,cross) => if(cross) t / ("scala-" + si.actualVersion) else t )
|
2011-02-06 03:40:10 +01:00
|
|
|
)
|
|
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
lazy val configTasks = Seq(
|
2011-02-10 14:16:07 +01:00
|
|
|
InitialCommands in GlobalScope :== "",
|
2011-02-05 04:02:39 +01:00
|
|
|
CompileTask <<= compileTask,
|
2011-02-06 03:40:10 +01:00
|
|
|
CompileInputs <<= compileInputsTask,
|
|
|
|
|
ConsoleTask <<= console,
|
|
|
|
|
ConsoleQuick <<= consoleQuick,
|
|
|
|
|
DiscoveredMainClasses <<= CompileTask map discoverMainClasses,
|
2011-02-26 00:35:52 +01:00
|
|
|
inTask(RunTask)(runner :: Nil).head,
|
2011-02-06 03:40:10 +01:00
|
|
|
SelectMainClass <<= DiscoveredMainClasses map selectRunMain,
|
2011-02-12 02:22:17 +01:00
|
|
|
MainClass in RunTask :== SelectMainClass,
|
|
|
|
|
MainClass <<= DiscoveredMainClasses map selectPackageMain,
|
2011-02-26 00:35:52 +01:00
|
|
|
RunTask <<= runTask(FullClasspath, MainClass in RunTask, Runner in RunTask),
|
2011-02-06 17:33:29 +01:00
|
|
|
ScaladocOptions <<= ScalacOptions(identity),
|
2011-02-06 19:01:50 +01:00
|
|
|
DocTask <<= docTask,
|
|
|
|
|
CopyResources <<= copyResources
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
lazy val projectTasks: Seq[Setting[_]] = Seq(
|
2011-02-06 17:33:29 +01:00
|
|
|
CleanFiles <<= (Target, SourceManaged) { _ :: _ :: Nil },
|
2011-02-25 05:30:06 +01:00
|
|
|
Clean <<= CleanFiles map IO.delete,
|
|
|
|
|
ConsoleProject <<= consoleProject
|
2011-02-06 17:33:29 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
lazy val testTasks = Seq(
|
|
|
|
|
TestLoader <<= (FullClasspath, ScalaInstance) map { (cp, si) => TestFramework.createTestLoader(data(cp), si) },
|
2011-02-10 14:16:07 +01:00
|
|
|
TestFrameworks in GlobalScope :== {
|
2011-02-06 17:33:29 +01:00
|
|
|
import sbt.TestFrameworks._
|
|
|
|
|
Seq(ScalaCheck, Specs, ScalaTest, ScalaCheckCompat, ScalaTestCompat, SpecsCompat, JUnit)
|
|
|
|
|
},
|
|
|
|
|
LoadedTestFrameworks <<= (TestFrameworks, streams, TestLoader) map { (frameworks, s, loader) =>
|
|
|
|
|
frameworks.flatMap(f => f.create(loader, s.log).map( x => (f,x)).toIterable).toMap
|
|
|
|
|
},
|
2011-02-12 02:22:17 +01:00
|
|
|
DefinedTests <<= (LoadedTestFrameworks, CompileTask, streams) map { (frameworkMap, analysis, s) =>
|
2011-02-26 00:35:52 +01:00
|
|
|
val tests = Test.discover(frameworkMap.values.toSeq, analysis, s.log)._1
|
2011-02-12 02:22:17 +01:00
|
|
|
IO.writeLines(s.text(CompletionsID), tests.map(_.name).distinct)
|
|
|
|
|
tests
|
2011-02-06 17:33:29 +01:00
|
|
|
},
|
|
|
|
|
TestListeners <<= (streams in TestTask) map ( s => TestLogger(s.log) :: Nil ),
|
|
|
|
|
TestOptions <<= TestListeners map { listeners => Test.Listeners(listeners) :: Nil },
|
2011-02-26 00:35:52 +01:00
|
|
|
ExecuteTests <<= (streams in TestTask, LoadedTestFrameworks, TestOptions, TestLoader, DefinedTests) flatMap {
|
|
|
|
|
(s, frameworkMap, options, loader, discovered) => Test(frameworkMap, loader, discovered, options, s.log)
|
2011-02-06 17:33:29 +01:00
|
|
|
},
|
2011-02-12 02:22:17 +01:00
|
|
|
TestTask <<= (ExecuteTests, streams) map { (results, s) => Test.showResults(s.log, results) },
|
|
|
|
|
TestOnly <<= testOnly
|
2011-02-06 03:40:10 +01:00
|
|
|
)
|
|
|
|
|
|
2011-02-12 02:22:17 +01:00
|
|
|
def testOnly =
|
|
|
|
|
InputTask(resolvedScoped(testOnlyParser)) ( result =>
|
2011-02-26 00:35:52 +01:00
|
|
|
(streams, LoadedTestFrameworks, TestOptions, TestLoader, DefinedTests, result) flatMap {
|
|
|
|
|
case (s, frameworks, opts, loader, discovered, (tests, frameworkOptions)) =>
|
2011-02-12 02:22:17 +01:00
|
|
|
val modifiedOpts = Test.Filter(if(tests.isEmpty) _ => true else tests.toSet ) +: Test.Argument(frameworkOptions : _*) +: opts
|
|
|
|
|
Test(frameworks, loader, discovered, modifiedOpts, s.log) map { results =>
|
|
|
|
|
Test.showResults(s.log, results)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)
|
2011-02-10 14:16:07 +01:00
|
|
|
|
|
|
|
|
lazy val packageBase = Seq(
|
|
|
|
|
jarName,
|
|
|
|
|
PackageOptions in GlobalScope :== Nil,
|
|
|
|
|
NameToString in GlobalScope :== (ArtifactName.show _)
|
|
|
|
|
)
|
|
|
|
|
lazy val packageConfig = Seq(
|
|
|
|
|
JarName <<= (JarName, Config) { (n,c) => n.copy(config = c.name) },
|
2011-02-23 04:36:48 +01:00
|
|
|
PackageOptions in Package <<= (PackageOptions, MainClass in Package) map { _ ++ _.map(sbt.Package.MainClass.apply).toList }
|
2011-02-10 14:16:07 +01:00
|
|
|
) ++
|
|
|
|
|
packageTasks(Package, "", packageBin) ++
|
|
|
|
|
packageTasks(PackageSrc, "src", packageSrc) ++
|
|
|
|
|
packageTasks(PackageDoc, "doc", packageDoc)
|
|
|
|
|
|
|
|
|
|
private[this] val allSubpaths = (_: File).###.***.xx.toSeq
|
|
|
|
|
|
2011-02-24 01:19:44 +01:00
|
|
|
def packageBin = concat(classMappings, resourceMappings)
|
2011-02-10 14:16:07 +01:00
|
|
|
def packageDoc = DocTask map allSubpaths
|
2011-02-24 01:19:44 +01:00
|
|
|
def packageSrc = concat(resourceMappings, sourceMappings)
|
|
|
|
|
|
|
|
|
|
private type Mappings = Initialize[Task[Seq[(File, String)]]]
|
|
|
|
|
def concat(as: Mappings, bs: Mappings) = (as zipWith bs)( (a,b) => (a :^: b :^: KNil) map { case a :+: b :+: HNil => a ++ b } )
|
|
|
|
|
def classMappings = (CompileInputs, CompileTask) map { (in, _) => allSubpaths(in.config.classesDirectory) }
|
|
|
|
|
// drop base directories, since there are no valid mappings for these
|
|
|
|
|
def sourceMappings = (Sources, SourceDirectories, Base) map { (srcs, sdirs, base) =>
|
|
|
|
|
( (srcs --- sdirs --- base) x (relativeTo(sdirs)|relativeTo(base))) toSeq
|
|
|
|
|
}
|
|
|
|
|
def resourceMappings = (Resources, ResourceDirectories) map { (rs, rdirs) =>
|
|
|
|
|
(rs --- rdirs) x relativeTo(rdirs) toSeq
|
2011-02-10 14:16:07 +01:00
|
|
|
}
|
2011-02-24 01:19:44 +01:00
|
|
|
|
2011-02-21 16:22:39 +01:00
|
|
|
def jarName = JarName <<= (ModuleName, Version, ScalaVersion, CrossPaths) { (n,v, sv, withCross) =>
|
|
|
|
|
ArtifactName(base = n, version = v, config = "", tpe = "", ext = "jar", cross = if(withCross) sv else "")
|
2011-02-10 14:16:07 +01:00
|
|
|
}
|
|
|
|
|
def jarPath = JarPath <<= (Target, JarName, NameToString) { (t, n, toString) => t / toString(n) }
|
|
|
|
|
|
2011-02-12 02:22:17 +01:00
|
|
|
def packageTasks(key: TaskKey[sbt.Package.Configuration], tpeString: String, mappings: Initialize[Task[Seq[(File,String)]]]) =
|
2011-02-10 14:16:07 +01:00
|
|
|
inTask(key)( Seq(
|
|
|
|
|
key in ThisScope.copy(task = Global) <<= packageTask,
|
|
|
|
|
Mappings <<= mappings,
|
|
|
|
|
JarType :== tpeString,
|
|
|
|
|
JarName <<= (JarType,JarName){ (tpe, name) => (name.copy(tpe = tpe)) },
|
|
|
|
|
CacheDirectory <<= CacheDirectory / key.key.label,
|
|
|
|
|
jarPath
|
|
|
|
|
))
|
2011-02-12 02:22:17 +01:00
|
|
|
def packageTask: Initialize[Task[sbt.Package.Configuration]] =
|
2011-02-10 14:16:07 +01:00
|
|
|
(JarPath, Mappings, PackageOptions, CacheDirectory, streams) map { (jar, srcs, options, cacheDir, s) =>
|
|
|
|
|
val config = new sbt.Package.Configuration(srcs, jar, options)
|
|
|
|
|
sbt.Package(config, cacheDir, s.log)
|
|
|
|
|
config
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-06 03:40:10 +01:00
|
|
|
def selectRunMain(classes: Seq[String]): Option[String] =
|
|
|
|
|
sbt.SelectMainClass(Some(SimpleReader readLine _), classes)
|
2011-02-12 02:22:17 +01:00
|
|
|
def selectPackageMain(classes: Seq[String]): Option[String] =
|
|
|
|
|
sbt.SelectMainClass(None, classes)
|
|
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
def runTask(classpath: ScopedTask[Classpath], mainClass: ScopedTask[Option[String]], run: ScopedSetting[ScalaRun]): Initialize[InputTask[Unit]] =
|
2011-02-12 02:22:17 +01:00
|
|
|
InputTask(_ => complete.Parsers.spaceDelimited("<arg>")) { result =>
|
2011-02-26 00:35:52 +01:00
|
|
|
(classpath, mainClass, run, streams, result) map { (cp, main, runner, s, args) =>
|
2011-02-12 02:22:17 +01:00
|
|
|
val mainClass = main getOrElse error("No main class detected.")
|
|
|
|
|
runner.run(mainClass, data(cp), args, s.log) foreach error
|
2011-02-06 03:40:10 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
def runner =
|
|
|
|
|
Runner <<= (ScalaInstance, Base, JavaOptions, OutputStrategy, Fork, JavaHome) { (si, base, options, strategy, fork, javaHome) =>
|
|
|
|
|
if(fork) {
|
|
|
|
|
new ForkRun( ForkOptions(scalaJars = si.jars, javaHome = javaHome, outputStrategy = strategy,
|
|
|
|
|
runJVMOptions = options, workingDirectory = Some(base)) )
|
|
|
|
|
} else
|
|
|
|
|
new Run(si)
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-12 02:22:17 +01:00
|
|
|
def docTask: Initialize[Task[File]] =
|
2011-02-06 17:33:29 +01:00
|
|
|
(CompileInputs, streams, DocDirectory, Config, ScaladocOptions) map { (in, s, target, config, options) =>
|
|
|
|
|
val d = new Scaladoc(in.config.maxErrors, in.compilers.scalac)
|
|
|
|
|
d(nameForSrc(config.name), in.config.sources, in.config.classpath, target, options)(s.log)
|
2011-02-10 14:16:07 +01:00
|
|
|
target
|
2011-02-06 17:33:29 +01:00
|
|
|
}
|
|
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
def mainRunTask = RunTask <<= runTask(FullClasspath in Configurations.Runtime, MainClass in RunTask, Runner in RunTask)
|
2011-02-06 03:40:10 +01:00
|
|
|
|
2011-02-27 05:56:30 +01:00
|
|
|
def discoverMainClasses(analysis: inc.Analysis): Seq[String] =
|
2011-02-06 03:40:10 +01:00
|
|
|
compile.Discovery.applications(Test.allDefs(analysis)) collect { case (definition, discovered) if(discovered.hasMain) => definition.name }
|
2011-02-25 05:30:06 +01:00
|
|
|
|
|
|
|
|
def consoleProject = (EvaluateTask.state, streams, InitialCommands in ConsoleProject) map { (state, s, extra) => Console.sbt(state, extra)(s.log) }
|
2011-02-06 03:40:10 +01:00
|
|
|
def console = consoleTask(FullClasspath, ConsoleTask)
|
|
|
|
|
def consoleQuick = consoleTask(ExternalDependencyClasspath, ConsoleQuick)
|
|
|
|
|
def consoleTask(classpath: TaskKey[Classpath], task: TaskKey[_]) = (Compilers, classpath, ScalacOptions in task, InitialCommands in task, streams) map {
|
|
|
|
|
(cs, cp, options, initialCommands, s) =>
|
|
|
|
|
(new Console(cs.scalac))(data(cp), options, initialCommands, s.log).foreach(msg => error(msg))
|
|
|
|
|
println()
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-05 04:02:39 +01:00
|
|
|
def compileTask = (CompileInputs, streams) map { (i,s) => Compile(i,s.log) }
|
2011-02-03 13:17:47 +01:00
|
|
|
def compileInputsTask =
|
|
|
|
|
(DependencyClasspath, Sources, JavaSourceRoots, Compilers, JavacOptions, ScalacOptions, CacheDirectory, ClassDirectory, streams) map {
|
2011-02-14 01:02:22 +01:00
|
|
|
(cp, sources, javaRoots, compilers, javacOptions, scalacOptions, cacheDirectory, classes, s) =>
|
2011-02-03 13:17:47 +01:00
|
|
|
val classpath = classes +: data(cp)
|
|
|
|
|
val analysis = analysisMap(cp)
|
|
|
|
|
val cache = cacheDirectory / "compile"
|
2011-02-06 17:33:29 +01:00
|
|
|
Compile.inputs(classpath, sources, classes, scalacOptions, javacOptions, javaRoots, analysis, cache, 100)(compilers, s.log)
|
2011-02-03 13:17:47 +01:00
|
|
|
}
|
|
|
|
|
|
2011-02-06 19:01:50 +01:00
|
|
|
def copyResources =
|
|
|
|
|
(ClassDirectory, CacheDirectory, Resources, ResourceDirectories, streams) map { (target, cache, resources, dirs, s) =>
|
|
|
|
|
val cacheFile = cache / "copy-resources"
|
2011-02-25 05:30:06 +01:00
|
|
|
val mappings = (resources --- dirs) x rebase(dirs, target)
|
2011-02-06 19:01:50 +01:00
|
|
|
s.log.debug("Copy resource mappings: " + mappings.mkString("\n\t","\n\t",""))
|
|
|
|
|
Sync(cacheFile)( mappings )
|
|
|
|
|
mappings
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-12 02:22:17 +01:00
|
|
|
def testOnlyParser(resolved: ScopedKey[_]): State => Parser[(Seq[String],Seq[String])] =
|
|
|
|
|
{ state =>
|
|
|
|
|
import DefaultParsers._
|
|
|
|
|
def distinctParser(exs: Set[String]): Parser[Seq[String]] =
|
|
|
|
|
token(Space ~> NotSpace.examples(exs)).flatMap(ex => distinctParser(exs - ex).map(ex +: _)) ?? Nil
|
|
|
|
|
val tests = savedLines(state, resolved, DefinedTests)
|
|
|
|
|
val selectTests = distinctParser(tests.toSet) // todo: proper IDs
|
|
|
|
|
val options = (Space ~> "--" ~> spaceDelimited("<arg>")) ?? Nil
|
|
|
|
|
selectTests ~ options
|
|
|
|
|
}
|
|
|
|
|
def savedLines(state: State, reader: ScopedKey[_], readFrom: Scoped): Seq[String] =
|
|
|
|
|
{
|
|
|
|
|
val structure = Project.structure(state)
|
|
|
|
|
structure.data.definingScope(reader.scope, readFrom.key) match {
|
|
|
|
|
case Some(defined) =>
|
|
|
|
|
val key = ScopedKey(Scope.fillTaskAxis(defined, readFrom.key), readFrom.key)
|
|
|
|
|
structure.streams.use(reader){ ts => IO.readLines(ts.readText(key, CompletionsID)) }
|
|
|
|
|
case None => Nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val CompletionsID = "completions"
|
2011-02-06 19:01:50 +01:00
|
|
|
|
2011-02-03 13:17:47 +01:00
|
|
|
def inConfig(conf: Configuration)(ss: Seq[Setting[_]]): Seq[Setting[_]] =
|
2011-02-10 14:16:07 +01:00
|
|
|
inScope(ThisScope.copy(config = Select(conf)) )( (Config :== 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)
|
2011-02-03 13:17:47 +01:00
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
lazy val defaultWebPaths = inConfig(CompileConf)(webPaths)
|
2011-02-21 16:07:58 +01:00
|
|
|
|
|
|
|
|
def noAggregation = Seq(RunTask, ConsoleTask, ConsoleQuick)
|
|
|
|
|
lazy val disableAggregation = noAggregation map disableAggregate
|
|
|
|
|
def disableAggregate(k: Scoped) =
|
|
|
|
|
Aggregate in Scope.GlobalScope.copy(task = Select(k.key)) :== false
|
|
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
lazy val baseTasks: Seq[Setting[_]] = projectTasks ++ packageBase
|
2011-02-06 03:40:10 +01:00
|
|
|
|
2011-02-03 13:17:47 +01:00
|
|
|
lazy val defaultWebTasks = Nil
|
|
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
lazy val baseClasspaths = Classpaths.publishSettings ++ Classpaths.baseSettings
|
|
|
|
|
lazy val configSettings = Classpaths.configSettings ++ configTasks ++ configPaths ++ packageConfig
|
|
|
|
|
|
|
|
|
|
lazy val compileSettings = configSettings ++ (mainRunTask +: addBaseSources)
|
|
|
|
|
lazy val testSettings = configSettings ++ testTasks
|
2011-02-03 13:17:47 +01:00
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
lazy val itSettings = inConfig(Configurations.IntegrationTest)(testSettings)
|
|
|
|
|
lazy val defaultConfigs = inConfig(CompileConf)(compileSettings) ++ inConfig(TestConf)(testSettings)
|
2011-02-03 13:17:47 +01:00
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
lazy val defaultSettings: Seq[Setting[_]] = core ++ paths ++ baseClasspaths ++ baseTasks ++ compileBase ++ defaultConfigs ++ disableAggregation
|
2011-02-03 13:17:47 +01:00
|
|
|
lazy val defaultWebSettings = defaultSettings ++ defaultWebPaths ++ defaultWebTasks
|
|
|
|
|
}
|
|
|
|
|
object Classpaths
|
|
|
|
|
{
|
|
|
|
|
import Path._
|
|
|
|
|
import GlobFilter._
|
|
|
|
|
import Keys._
|
|
|
|
|
import Scope.ThisScope
|
|
|
|
|
import Default._
|
2011-02-05 04:02:39 +01:00
|
|
|
import Attributed.{blank, blankSeq}
|
2011-02-03 13:17:47 +01:00
|
|
|
|
2011-02-12 02:22:17 +01:00
|
|
|
def concat[T](a: ScopedTaskable[Seq[T]], b: ScopedTaskable[Seq[T]]): Initialize[Task[Seq[T]]] = (a,b) map (_ ++ _)
|
2011-02-03 13:17:47 +01:00
|
|
|
|
2011-02-27 05:56:30 +01:00
|
|
|
lazy val configSettings: Seq[Setting[_]] = Seq(
|
2011-02-05 04:02:39 +01:00
|
|
|
ExternalDependencyClasspath <<= concat(UnmanagedClasspath, ManagedClasspath),
|
|
|
|
|
DependencyClasspath <<= concat(InternalDependencyClasspath, ExternalDependencyClasspath),
|
2011-02-20 05:25:30 +01:00
|
|
|
FullClasspath <<= concat(Products, DependencyClasspath),
|
2011-02-05 04:02:39 +01:00
|
|
|
InternalDependencyClasspath <<= internalDependencies,
|
2011-02-20 05:25:30 +01:00
|
|
|
UnmanagedClasspath <<= unmanagedDependencies,
|
2011-02-05 04:02:39 +01:00
|
|
|
Products <<= makeProducts,
|
|
|
|
|
ManagedClasspath <<= (Config, Update) map { (config, up) => up.getOrElse(config.name, error("Configuration '" + config.name + "' unresolved by 'update'.")) },
|
2011-02-20 05:25:30 +01:00
|
|
|
UnmanagedJars <<= (Config, UnmanagedBase, ClasspathFilter, DefaultExcludes) map { (config, base, filter, excl) =>
|
2011-02-05 04:02:39 +01:00
|
|
|
(base * (filter -- excl) +++ (base / config.name).descendentsExcept(filter, excl)).getFiles.toSeq
|
|
|
|
|
}
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
2011-02-10 14:16:07 +01:00
|
|
|
def defaultPackageTasks: Seq[ScopedTask[_]] =
|
|
|
|
|
for(task <- Seq(Package, PackageSrc, PackageDoc); conf <- Seq(CompileConf, TestConf)) yield (task in conf)
|
2011-02-03 13:17:47 +01:00
|
|
|
|
2011-02-27 05:56:30 +01:00
|
|
|
val publishSettings: Seq[Setting[_]] = Seq(
|
2011-02-10 14:16:07 +01:00
|
|
|
PublishMavenStyle in GlobalScope :== true,
|
|
|
|
|
PackageToPublish <<= defaultPackageTasks.dependOn,
|
2011-02-12 02:22:17 +01:00
|
|
|
DeliverDepends <<= (PublishMavenStyle, MakePom.setting, PackageToPublish.setting) { (mavenStyle, makePom, ptp) =>
|
|
|
|
|
if(mavenStyle) makePom.map(_ => ()) else ptp
|
|
|
|
|
},
|
2011-02-05 04:02:39 +01:00
|
|
|
MakePom <<= (IvyModule, MakePomConfig, PackageToPublish) map { (ivyModule, makePomConfig, _) => IvyActions.makePom(ivyModule, makePomConfig); makePomConfig.file },
|
|
|
|
|
Deliver <<= deliver(PublishConfig),
|
|
|
|
|
DeliverLocal <<= deliver(PublishLocalConfig),
|
|
|
|
|
Publish <<= publish(PublishConfig, Deliver),
|
|
|
|
|
PublishLocal <<= publish(PublishLocalConfig, DeliverLocal)
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
2011-02-27 05:56:30 +01:00
|
|
|
val baseSettings: Seq[Setting[_]] = Seq(
|
2011-02-05 04:02:39 +01:00
|
|
|
UnmanagedBase <<= Base / "lib",
|
|
|
|
|
NormalizedName <<= Name(StringUtilities.normalize),
|
2011-02-03 13:17:47 +01:00
|
|
|
Organization :== NormalizedName,
|
2011-02-10 14:16:07 +01:00
|
|
|
ClasspathFilter in GlobalScope :== "*.jar",
|
2011-02-05 04:02:39 +01:00
|
|
|
Resolvers <<= (ProjectResolver,BaseResolvers).map( (pr,rs) => pr +: Resolver.withDefaultResolvers(rs)),
|
2011-02-10 14:16:07 +01:00
|
|
|
Offline in GlobalScope :== false,
|
2011-02-03 13:17:47 +01:00
|
|
|
ModuleName :== NormalizedName,
|
2011-02-10 14:16:07 +01:00
|
|
|
DefaultConfiguration in GlobalScope :== Some(Configurations.Compile),
|
|
|
|
|
DefaultConfigurationMapping in GlobalScope <<= DefaultConfiguration{ case Some(d) => "*->" + d.name; case None => "*->*" },
|
2011-02-05 04:02:39 +01:00
|
|
|
PathsIvy <<= Base(base => new IvyPaths(base, None)),
|
2011-02-10 14:16:07 +01:00
|
|
|
OtherResolvers in GlobalScope :== Nil,
|
2011-02-05 04:02:39 +01:00
|
|
|
ProjectResolver <<= projectResolver,
|
|
|
|
|
ProjectDependencies <<= projectDependencies,
|
2011-02-10 14:16:07 +01:00
|
|
|
LibraryDependencies in GlobalScope :== Nil,
|
2011-02-05 04:02:39 +01:00
|
|
|
AllDependencies <<= concat(ProjectDependencies,LibraryDependencies),
|
2011-02-10 14:16:07 +01:00
|
|
|
IvyLoggingLevel in GlobalScope :== UpdateLogging.Quiet,
|
|
|
|
|
IvyXML in GlobalScope :== NodeSeq.Empty,
|
|
|
|
|
IvyValidate in GlobalScope :== false,
|
2011-02-15 00:57:10 +01:00
|
|
|
IvyScalaConfig in GlobalScope <<= ScalaVersion(v => Some(new IvyScala(v, Nil, false, false))),
|
2011-02-10 14:16:07 +01:00
|
|
|
ModuleConfigurations in GlobalScope :== Nil,
|
|
|
|
|
PublishTo in GlobalScope :== None,
|
2011-02-21 16:22:39 +01:00
|
|
|
PomName <<= (ModuleName, Version, ScalaVersion, CrossPaths) { (n,v,sv, withCross) =>
|
|
|
|
|
ArtifactName(base = n, version = v, config = "", tpe = "", ext = "pom", cross = if(withCross) sv else "")
|
|
|
|
|
},
|
|
|
|
|
PomFile <<= (Target, PomName, NameToString) { (t, n, toString) => t / toString(n) },
|
2011-02-10 14:16:07 +01:00
|
|
|
PomArtifact <<= (PublishMavenStyle, ModuleName)( (mavenStyle, name) => if(mavenStyle) Artifact(name, "pom", "pom") :: Nil else Nil),
|
|
|
|
|
Artifacts <<= (PomArtifact,ModuleName)( (pom,name) => Artifact(name) +: pom),
|
2011-02-05 04:02:39 +01:00
|
|
|
ProjectID <<= (Organization,ModuleName,Version,Artifacts){ (org,module,version,as) => ModuleID(org, module, version).cross(true).artifacts(as : _*) },
|
2011-02-10 14:16:07 +01:00
|
|
|
BaseResolvers in GlobalScope :== Nil,
|
2011-02-05 04:02:39 +01:00
|
|
|
ProjectDescriptors <<= depMap,
|
2011-02-03 13:17:47 +01:00
|
|
|
RetrievePattern :== "[type]/[organisation]/[module]/[artifact](-[revision])(-[classifier]).[ext]",
|
2011-02-05 04:02:39 +01:00
|
|
|
UpdateConfig <<= (RetrieveConfig, IvyLoggingLevel)((conf,level) => new UpdateConfiguration(conf, level) ),
|
2011-02-03 13:17:47 +01:00
|
|
|
RetrieveConfig :== None, //Some(new RetrieveConfiguration(managedDependencyPath asFile, retrievePattern, true))
|
2011-02-05 04:02:39 +01:00
|
|
|
IvyConfig <<= (Resolvers, PathsIvy, OtherResolvers, ModuleConfigurations, Offline, AppConfig) map { (rs, paths, otherResolvers, moduleConfigurations, offline, app) =>
|
2011-02-03 13:17:47 +01:00
|
|
|
// todo: pass logger from streams directly to IvyActions
|
|
|
|
|
val lock = app.provider.scalaProvider.launcher.globalLock
|
|
|
|
|
new InlineIvyConfiguration(paths, rs, otherResolvers, moduleConfigurations, offline, Some(lock), ConsoleLogger())
|
2011-02-05 04:02:39 +01:00
|
|
|
},
|
|
|
|
|
ModuleSettingsTask <<= (ProjectID, AllDependencies, IvyXML, ThisProject, DefaultConfiguration, IvyScalaConfig, IvyValidate) map {
|
2011-02-03 13:17:47 +01:00
|
|
|
(pid, deps, ivyXML, project, defaultConf, ivyScala, validate) => new InlineConfiguration(pid, deps, ivyXML, project.configurations, defaultConf, ivyScala, validate)
|
2011-02-05 04:02:39 +01:00
|
|
|
},
|
|
|
|
|
MakePomConfig <<= PomFile(pomFile => makePomConfiguration(pomFile)),
|
|
|
|
|
PublishConfig <<= (Target, PublishTo, IvyLoggingLevel) map { (outputDirectory, publishTo, level) => publishConfiguration( publishPatterns(outputDirectory), resolverName = getPublishTo(publishTo).name, logging = level) },
|
|
|
|
|
PublishLocalConfig <<= (Target, IvyLoggingLevel) map { (outputDirectory, level) => publishConfiguration( publishPatterns(outputDirectory, true), logging = level ) },
|
|
|
|
|
IvySbtTask <<= IvyConfig map { conf => new IvySbt(conf) },
|
|
|
|
|
IvyModule <<= (IvySbtTask, ModuleSettingsTask) map { (ivySbt, settings) => new ivySbt.Module(settings) },
|
|
|
|
|
Update <<= (IvyModule, UpdateConfig, CacheDirectory, streams) map { (ivyModule, updateConfig, cacheDirectory, s) =>
|
2011-02-03 13:17:47 +01:00
|
|
|
cachedUpdate(cacheDirectory / "update", ivyModule, updateConfig, s.log)
|
2011-02-05 04:02:39 +01:00
|
|
|
}
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2011-02-12 02:22:17 +01:00
|
|
|
def deliver(config: TaskKey[PublishConfiguration]): Initialize[Task[Unit]] =
|
2011-02-03 13:17:47 +01:00
|
|
|
(IvyModule, config, DeliverDepends) map { (ivyModule, config, _) => IvyActions.deliver(ivyModule, config) }
|
2011-02-12 02:22:17 +01:00
|
|
|
def publish(config: TaskKey[PublishConfiguration], deliverKey: TaskKey[_]): Initialize[Task[Unit]] =
|
2011-02-03 13:17:47 +01:00
|
|
|
(IvyModule, config, deliverKey) map { (ivyModule, config, _) => IvyActions.publish(ivyModule, config) }
|
|
|
|
|
|
|
|
|
|
import Cache._
|
|
|
|
|
import CacheIvy.{classpathFormat, publishIC, updateIC}
|
|
|
|
|
|
|
|
|
|
def cachedUpdate(cacheFile: File, module: IvySbt#Module, config: UpdateConfiguration, log: Logger): Map[String, Seq[File]] =
|
|
|
|
|
{
|
|
|
|
|
implicit val updateCache = updateIC
|
|
|
|
|
val work = (_: IvyConfiguration :+: ModuleSettings :+: UpdateConfiguration :+: HNil) match { case conf :+: settings :+: config :+: HNil =>
|
|
|
|
|
log.info("Updating...")
|
|
|
|
|
val r = IvyActions.update(module, config)
|
|
|
|
|
log.info("Done updating.")
|
|
|
|
|
r
|
|
|
|
|
}
|
|
|
|
|
val f = cached(cacheFile)(work)
|
|
|
|
|
f(module.owner.configuration :+: module.moduleSettings :+: config :+: HNil)
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
// can't cache deliver/publish easily since files involved are hidden behind patterns. publish will be difficult to verify target-side anyway
|
|
|
|
|
def cachedPublish(cacheFile: File)(g: (IvySbt#Module, PublishConfiguration) => Unit, module: IvySbt#Module, config: PublishConfiguration) => Unit =
|
|
|
|
|
{ case module :+: config :+: HNil =>
|
|
|
|
|
/* implicit val publishCache = publishIC
|
|
|
|
|
val f = cached(cacheFile) { (conf: IvyConfiguration, settings: ModuleSettings, config: PublishConfiguration) =>*/
|
|
|
|
|
g(module, config)
|
|
|
|
|
/*}
|
|
|
|
|
f(module.owner.configuration :+: module.moduleSettings :+: config :+: HNil)*/
|
|
|
|
|
}*/
|
|
|
|
|
def makePomConfiguration(file: File, configurations: Option[Iterable[Configuration]] = None, extra: NodeSeq = NodeSeq.Empty, process: XNode => XNode = n => n, filterRepositories: MavenRepository => Boolean = _ => true) =
|
|
|
|
|
new MakePomConfiguration(file, configurations, extra, process, filterRepositories)
|
|
|
|
|
|
|
|
|
|
def getPublishTo(repo: Option[Resolver]): Resolver = repo getOrElse error("Repository for publishing is not specified.")
|
|
|
|
|
|
|
|
|
|
def publishConfiguration(patterns: PublishPatterns, resolverName: String = "local", status: String = "release", logging: UpdateLogging.Value = UpdateLogging.DownloadOnly) =
|
|
|
|
|
new PublishConfiguration(patterns, status, resolverName, None, logging)
|
|
|
|
|
|
|
|
|
|
def publishPatterns(outputPath: Path, publishIvy: Boolean = false): PublishPatterns =
|
|
|
|
|
{
|
|
|
|
|
val deliverPattern = (outputPath / "[artifact]-[revision](-[classifier]).[ext]").absolutePath
|
|
|
|
|
val srcArtifactPatterns: Seq[String] =
|
|
|
|
|
{
|
|
|
|
|
val pathPatterns =
|
|
|
|
|
(outputPath / "[artifact]-[revision]-[type](-[classifier]).[ext]") ::
|
|
|
|
|
(outputPath / "[artifact]-[revision](-[classifier]).[ext]") ::
|
|
|
|
|
Nil
|
|
|
|
|
pathPatterns.map(_.absolutePath)
|
|
|
|
|
}
|
|
|
|
|
new PublishPatterns( if(publishIvy) Some(deliverPattern) else None, srcArtifactPatterns)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def projectDependencies =
|
|
|
|
|
(ThisProject, Data) map { (p, data) =>
|
2011-02-05 04:02:39 +01:00
|
|
|
p.dependencies flatMap { dep => (ProjectID in dep.project) get data map { _.copy(configurations = dep.configuration) } }
|
2011-02-03 13:17:47 +01:00
|
|
|
}
|
|
|
|
|
|
2011-02-12 02:22:17 +01:00
|
|
|
def depMap: Initialize[Task[Map[ModuleRevisionId, ModuleDescriptor]]] =
|
2011-02-03 13:17:47 +01:00
|
|
|
(ThisProject, ThisProjectRef, Data) flatMap { (root, rootRef, data) =>
|
2011-02-05 04:02:39 +01:00
|
|
|
val dependencies = (p: (ProjectRef, Project)) => p._2.dependencies.flatMap(pr => ThisProject in pr.project get data map { (pr.project, _) })
|
2011-02-03 13:17:47 +01:00
|
|
|
depMap(Dag.topologicalSort((rootRef,root))(dependencies).dropRight(1), data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def depMap(projects: Seq[(ProjectRef,Project)], data: Settings[Scope]): Task[Map[ModuleRevisionId, ModuleDescriptor]] =
|
2011-02-05 04:02:39 +01:00
|
|
|
projects.flatMap { case (p,_) => IvyModule in p get data }.join.map { mods =>
|
2011-02-03 13:17:47 +01:00
|
|
|
(mods.map{ mod =>
|
|
|
|
|
val md = mod.moduleDescriptor
|
|
|
|
|
(md.getModuleRevisionId, md)
|
|
|
|
|
}).toMap
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-12 02:22:17 +01:00
|
|
|
def projectResolver: Initialize[Task[Resolver]] =
|
2011-02-03 13:17:47 +01:00
|
|
|
ProjectDescriptors map { m =>
|
|
|
|
|
new RawRepository(new ProjectResolver("inter-project", m))
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-27 05:56:30 +01:00
|
|
|
def analyzed[T](data: T, analysis: inc.Analysis) = Attributed.blank(data).put(Keys.Analysis, analysis)
|
2011-02-12 02:22:17 +01:00
|
|
|
def makeProducts: Initialize[Task[Classpath]] =
|
2011-02-26 00:35:52 +01:00
|
|
|
(CompileTask, CompileInputs, CopyResources) map { (analysis, i, _) => analyzed(i.config.classesDirectory, analysis) :: Nil }
|
2011-02-03 13:17:47 +01:00
|
|
|
|
2011-02-12 02:22:17 +01:00
|
|
|
def internalDependencies: Initialize[Task[Classpath]] =
|
2011-02-03 13:17:47 +01:00
|
|
|
(ThisProjectRef, ThisProject, Config, Data) flatMap internalDependencies0
|
2011-02-20 05:25:30 +01:00
|
|
|
def unmanagedDependencies: Initialize[Task[Classpath]] =
|
|
|
|
|
(ThisProjectRef, ThisProject, Config, Data) flatMap unmanagedDependencies0
|
2011-02-03 13:17:47 +01:00
|
|
|
|
2011-02-20 05:25:30 +01:00
|
|
|
import java.util.LinkedHashSet
|
|
|
|
|
import collection.JavaConversions.asScalaSet
|
|
|
|
|
def interSort(projectRef: ProjectRef, project: Project, conf: Configuration, data: Settings[Scope]): Seq[(ProjectRef,String)] =
|
2011-02-03 13:17:47 +01:00
|
|
|
{
|
|
|
|
|
val visited = asScalaSet(new LinkedHashSet[(ProjectRef,String)])
|
|
|
|
|
def visit(p: ProjectRef, project: Project, c: Configuration)
|
|
|
|
|
{
|
|
|
|
|
val applicableConfigs = allConfigs(c)
|
|
|
|
|
for(ac <- applicableConfigs) // add all configurations in this project
|
|
|
|
|
visited add (p, ac.name)
|
|
|
|
|
val masterConfs = configurationNames(project)
|
|
|
|
|
|
|
|
|
|
for( Project.ClasspathDependency(dep, confMapping) <- project.dependencies)
|
|
|
|
|
{
|
2011-02-05 04:02:39 +01:00
|
|
|
val depProject = ThisProject in dep get data getOrElse error("Invalid project: " + dep)
|
2011-02-03 13:17:47 +01:00
|
|
|
val mapping = mapped(confMapping, masterConfs, configurationNames(depProject), "compile", "*->compile")
|
|
|
|
|
// map master configuration 'c' and all extended configurations to the appropriate dependency configuration
|
|
|
|
|
for(ac <- applicableConfigs; depConfName <- mapping(ac.name))
|
|
|
|
|
{
|
|
|
|
|
val depConf = configuration(dep, depProject, depConfName)
|
|
|
|
|
if( ! visited( (dep, depConfName) ) )
|
|
|
|
|
visit(dep, depProject, depConf)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
visit(projectRef, project, conf)
|
2011-02-20 05:25:30 +01:00
|
|
|
visited.toSeq
|
|
|
|
|
}
|
|
|
|
|
def unmanagedDependencies0(projectRef: ProjectRef, project: Project, conf: Configuration, data: Settings[Scope]): Task[Classpath] =
|
2011-02-20 21:40:29 +01:00
|
|
|
interDependencies(projectRef, project, conf, data, true, unmanagedLibs)
|
2011-02-20 05:25:30 +01:00
|
|
|
def internalDependencies0(projectRef: ProjectRef, project: Project, conf: Configuration, data: Settings[Scope]): Task[Classpath] =
|
2011-02-20 21:40:29 +01:00
|
|
|
interDependencies(projectRef, project, conf, data, false, products)
|
|
|
|
|
def interDependencies(projectRef: ProjectRef, project: Project, conf: Configuration, data: Settings[Scope], includeSelf: Boolean,
|
2011-02-20 05:25:30 +01:00
|
|
|
f: (ProjectRef, String, Settings[Scope]) => Task[Classpath]): Task[Classpath] =
|
|
|
|
|
{
|
|
|
|
|
val visited = interSort(projectRef, project, conf, data)
|
2011-02-20 21:40:29 +01:00
|
|
|
val tasks = asScalaSet(new LinkedHashSet[Task[Classpath]])
|
2011-02-03 13:17:47 +01:00
|
|
|
for( (dep, c) <- visited )
|
2011-02-20 21:40:29 +01:00
|
|
|
if(includeSelf || (dep != projectRef) || conf.name != c )
|
|
|
|
|
tasks += f(dep, c, data)
|
2011-02-03 13:17:47 +01:00
|
|
|
|
2011-02-20 21:40:29 +01:00
|
|
|
(tasks.toSeq.join).map(_.flatten.distinct)
|
2011-02-03 13:17:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def mapped(confString: Option[String], masterConfs: Seq[String], depConfs: Seq[String], default: String, defaultMapping: String): String => Seq[String] =
|
|
|
|
|
{
|
|
|
|
|
lazy val defaultMap = parseMapping(defaultMapping, masterConfs, depConfs, _ :: Nil)
|
|
|
|
|
parseMapping(confString getOrElse default, masterConfs, depConfs, defaultMap)
|
|
|
|
|
}
|
|
|
|
|
def parseMapping(confString: String, masterConfs: Seq[String], depConfs: Seq[String], default: String => Seq[String]): String => Seq[String] =
|
|
|
|
|
union(confString.split(";") map parseSingleMapping(masterConfs, depConfs, default))
|
|
|
|
|
def parseSingleMapping( masterConfs: Seq[String], depConfs: Seq[String], default: String => Seq[String])(confString: String): String => Seq[String] =
|
|
|
|
|
{
|
|
|
|
|
val ms: Seq[(String,Seq[String])] =
|
|
|
|
|
trim(confString.split("->",2)) match {
|
|
|
|
|
case x :: Nil => for(a <- parseList(x, masterConfs)) yield (a,default(a))
|
|
|
|
|
case x :: y :: Nil => val target = parseList(y, depConfs); for(a <- parseList(x, masterConfs)) yield (a,target)
|
|
|
|
|
case _ => error("Invalid configuration '" + confString + "'") // shouldn't get here
|
|
|
|
|
}
|
|
|
|
|
val m = ms.toMap
|
|
|
|
|
s => m.getOrElse(s, Nil)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def union[A,B](maps: Seq[A => Seq[B]]): A => Seq[B] =
|
|
|
|
|
a => (Seq[B]() /: maps) { _ ++ _(a) } distinct;
|
|
|
|
|
|
|
|
|
|
def configurationNames(p: Project): Seq[String] = p.configurations.map( _.name)
|
|
|
|
|
def parseList(s: String, allConfs: Seq[String]): Seq[String] = (trim(s split ",") flatMap replaceWildcard(allConfs)).distinct
|
|
|
|
|
def replaceWildcard(allConfs: Seq[String])(conf: String): Seq[String] =
|
|
|
|
|
if(conf == "") Nil else if(conf == "*") allConfs else conf :: Nil
|
|
|
|
|
|
|
|
|
|
private def trim(a: Array[String]): List[String] = a.toList.map(_.trim)
|
|
|
|
|
def missingConfiguration(in: String, conf: String) =
|
|
|
|
|
error("Configuration '" + conf + "' not defined in '" + in + "'")
|
|
|
|
|
def allConfigs(conf: Configuration): Seq[Configuration] =
|
|
|
|
|
Dag.topologicalSort(conf)(_.extendsConfigs)
|
|
|
|
|
|
|
|
|
|
def configuration(ref: ProjectRef, dep: Project, conf: String): Configuration =
|
|
|
|
|
dep.configurations.find(_.name == conf) getOrElse missingConfiguration(Project display ref, conf)
|
|
|
|
|
def products(dep: ProjectRef, conf: String, data: Settings[Scope]): Task[Classpath] =
|
2011-02-20 05:25:30 +01:00
|
|
|
getClasspath(Products, dep, conf, data)
|
|
|
|
|
def unmanagedLibs(dep: ProjectRef, conf: String, data: Settings[Scope]): Task[Classpath] =
|
|
|
|
|
getClasspath(UnmanagedJars, dep, conf, data)
|
|
|
|
|
def getClasspath(key: TaskKey[Classpath], dep: ProjectRef, conf: String, data: Settings[Scope]): Task[Classpath] =
|
|
|
|
|
( key in (dep, ConfigKey(conf)) ) get data getOrElse const(Nil)
|
2011-02-03 13:17:47 +01:00
|
|
|
def defaultConfiguration(p: ProjectRef, data: Settings[Scope]): Configuration =
|
2011-02-05 04:02:39 +01:00
|
|
|
flatten(DefaultConfiguration in p get data) getOrElse Configurations.Default
|
2011-02-03 13:17:47 +01:00
|
|
|
def flatten[T](o: Option[Option[T]]): Option[T] = o flatMap identity
|
|
|
|
|
}
|