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-27 22:28:00 +01:00
|
|
|
import Scope.{GlobalScope, ThisScope}
|
2011-03-02 12:46:28 +01:00
|
|
|
import compiler.Discovery
|
2011-02-27 22:28:00 +01:00
|
|
|
import Project.{inConfig, Initialize, inScope, inTask, 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-03-05 14:25:17 +01:00
|
|
|
object Defaults
|
2011-02-03 13:17:47 +01:00
|
|
|
{
|
|
|
|
|
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-03-02 12:46:28 +01:00
|
|
|
def configSrcSub(key: ScopedSetting[File]): Initialize[File] = (key, configuration) { (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) =
|
2011-03-02 12:46:28 +01:00
|
|
|
(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-27 22:28:00 +01:00
|
|
|
def buildCore: Seq[Setting[_]] = inScope(GlobalScope)(Seq(
|
2011-03-10 00:04:53 +01:00
|
|
|
pollInterval :== 500,
|
|
|
|
|
scalaHome :== None,
|
2011-03-02 12:46:28 +01:00
|
|
|
javaHome :== None,
|
|
|
|
|
outputStrategy :== None,
|
|
|
|
|
fork :== false,
|
|
|
|
|
javaOptions :== Nil,
|
|
|
|
|
crossPaths :== true,
|
2011-03-03 12:44:19 +01:00
|
|
|
// shellPrompt :== (_ => "> "),
|
2011-03-02 12:46:28 +01:00
|
|
|
aggregate :== Aggregation.Enabled,
|
|
|
|
|
maxErrors :== 100,
|
2011-03-07 03:57:31 +01:00
|
|
|
showTiming :== true,
|
|
|
|
|
timingFormat :== Aggregation.defaultFormat,
|
|
|
|
|
showSuccess :== true,
|
2011-03-02 12:46:28 +01:00
|
|
|
commands :== Nil,
|
|
|
|
|
settings <<= EvaluateTask.state map { state => Project.structure(state).data }
|
2011-02-27 22:28:00 +01:00
|
|
|
))
|
|
|
|
|
def projectCore: Seq[Setting[_]] = Seq(
|
2011-03-02 12:46:28 +01:00
|
|
|
name <<= thisProject(_.id),
|
|
|
|
|
version :== "0.1"
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
def paths = Seq(
|
2011-03-02 12:46:28 +01:00
|
|
|
baseDirectory <<= thisProject(_.base),
|
|
|
|
|
target <<= baseDirectory / "target",
|
|
|
|
|
defaultExcludes in GlobalScope :== (".*" - ".") || HiddenFileFilter,
|
|
|
|
|
historyPath <<= target(t => Some(t / ".history")),
|
|
|
|
|
cacheDirectory <<= target / "cache",
|
|
|
|
|
sourceDirectory <<= baseDirectory / "src",
|
|
|
|
|
sourceFilter in GlobalScope :== ("*.java" | "*.scala"),
|
|
|
|
|
sourceManaged <<= baseDirectory / "src_managed"
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
lazy val configPaths = Seq(
|
2011-03-02 12:46:28 +01:00
|
|
|
sourceDirectory <<= configSrcSub( sourceDirectory in Scope(This,Global,This,This) ),
|
|
|
|
|
sourceManaged <<= configSrcSub(sourceManaged),
|
|
|
|
|
cacheDirectory <<= (cacheDirectory, configuration) { _ / _.name },
|
|
|
|
|
classDirectory <<= (target, configuration) { (outDir, conf) => outDir / (prefix(conf.name) + "classes") },
|
|
|
|
|
docDirectory <<= (target, configuration) { (outDir, conf) => outDir / (prefix(conf.name) + "api") },
|
|
|
|
|
sources <<= (sourceDirectories, sourceFilter, defaultExcludes) map { (d,f,excl) => d.descendentsExcept(f,excl).getFiles.toSeq },
|
|
|
|
|
scalaSource <<= sourceDirectory / "scala",
|
|
|
|
|
javaSource <<= sourceDirectory / "java",
|
|
|
|
|
resourceDirectory <<= sourceDirectory / "resources",
|
2011-03-10 00:04:53 +01:00
|
|
|
sourceDirectories <<= (scalaSource, javaSource) { _ :: _ :: Nil },
|
2011-03-02 12:46:28 +01:00
|
|
|
resourceDirectories <<= toSeq(resourceDirectory),
|
|
|
|
|
resources <<= (resourceDirectories, defaultExcludes) map { (dirs, excl) => dirs.descendentsExcept("*",excl).getFiles.toSeq }
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
def addBaseSources = Seq(
|
2011-03-02 12:46:28 +01:00
|
|
|
sources <<= (sources, baseDirectory, 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-03-02 12:46:28 +01:00
|
|
|
webappDir <<= sourceDirectory / "webapp"
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def compileBase = Seq(
|
2011-03-08 23:50:19 +01:00
|
|
|
classpathOptions in GlobalScope :== ClasspathOptions.auto,
|
2011-03-10 00:04:53 +01:00
|
|
|
compilers <<= (scalaInstance, appConfiguration, streams, classpathOptions, javaHome) map { (si, app, s, co, jh) => Compiler.compilers(si, co, jh)(app, s.log) },
|
2011-03-02 12:46:28 +01:00
|
|
|
javacOptions in GlobalScope :== Nil,
|
|
|
|
|
scalacOptions in GlobalScope :== Nil,
|
2011-03-10 00:04:53 +01:00
|
|
|
scalaInstance <<= scalaInstanceSetting,
|
2011-03-02 12:46:28 +01:00
|
|
|
scalaVersion <<= appConfiguration( _.provider.scalaProvider.version),
|
|
|
|
|
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-03-02 12:46:28 +01:00
|
|
|
initialCommands in GlobalScope :== "",
|
|
|
|
|
compile <<= compileTask,
|
|
|
|
|
compileInputs <<= compileInputsTask,
|
|
|
|
|
console <<= consoleTask,
|
|
|
|
|
consoleQuick <<= consoleQuickTask,
|
|
|
|
|
discoveredMainClasses <<= compile map discoverMainClasses,
|
|
|
|
|
inTask(run)(runnerSetting :: Nil).head,
|
|
|
|
|
selectMainClass <<= discoveredMainClasses map selectRunMain,
|
|
|
|
|
mainClass in run :== selectMainClass,
|
|
|
|
|
mainClass <<= discoveredMainClasses map selectPackageMain,
|
|
|
|
|
run <<= runTask(fullClasspath, mainClass in run, runner in run),
|
|
|
|
|
scaladocOptions <<= scalacOptions(identity),
|
|
|
|
|
doc <<= docTask,
|
|
|
|
|
copyResources <<= copyResourcesTask
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
lazy val projectTasks: Seq[Setting[_]] = Seq(
|
2011-03-02 12:46:28 +01:00
|
|
|
cleanFiles <<= (target, sourceManaged) { _ :: _ :: Nil },
|
|
|
|
|
clean <<= cleanFiles map IO.delete,
|
|
|
|
|
consoleProject <<= consoleProjectTask,
|
|
|
|
|
watchSources <<= watchSourcesTask,
|
|
|
|
|
watchTransitiveSources <<= watchTransitiveSourcesTask,
|
|
|
|
|
watch <<= watchSetting
|
2011-02-06 17:33:29 +01:00
|
|
|
)
|
|
|
|
|
|
2011-03-02 12:46:28 +01:00
|
|
|
def inAllConfigurations[T](key: ScopedTask[T]): Initialize[Task[Seq[T]]] = (EvaluateTask.state, thisProjectRef) flatMap { (state, ref) =>
|
2011-03-01 14:54:06 +01:00
|
|
|
val structure = Project structure state
|
|
|
|
|
val configurations = Project.getProject(ref, structure).toList.flatMap(_.configurations)
|
|
|
|
|
configurations.flatMap { conf =>
|
|
|
|
|
key in (ref, conf) get structure.data
|
|
|
|
|
} join
|
|
|
|
|
}
|
2011-03-02 12:46:28 +01:00
|
|
|
def watchTransitiveSourcesTask: Initialize[Task[Seq[File]]] =
|
|
|
|
|
(EvaluateTask.state, thisProjectRef) flatMap { (s, base) =>
|
|
|
|
|
inAllDependencies(base, watchSources.setting, Project structure s).join.map(_.flatten)
|
2011-03-01 14:54:06 +01:00
|
|
|
}
|
2011-03-02 12:46:28 +01:00
|
|
|
def watchSourcesTask: Initialize[Task[Seq[File]]] = Seq(sources, resources).map(inAllConfigurations).join { _.join.map(_.flatten.flatten) }
|
2011-03-01 14:54:06 +01:00
|
|
|
|
2011-03-02 12:46:28 +01:00
|
|
|
def watchSetting: Initialize[Watched] = (pollInterval, thisProjectRef) { (interval, base) =>
|
2011-03-01 14:54:06 +01:00
|
|
|
new Watched {
|
2011-03-02 12:46:28 +01:00
|
|
|
val scoped = watchTransitiveSources in base
|
2011-03-01 14:54:06 +01:00
|
|
|
val key = ScopedKey(scoped.scope, scoped.key)
|
|
|
|
|
override def pollInterval = interval
|
|
|
|
|
override def watchPaths(s: State) = EvaluateTask.evaluateTask(Project structure s, key, s, base) match { case Some(Value(ps)) => ps; case _ => Nil }
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-10 00:04:53 +01:00
|
|
|
def scalaInstanceSetting = (appConfiguration, scalaVersion, scalaHome){ (app, version, home) =>
|
|
|
|
|
val launcher = app.provider.scalaProvider.launcher
|
|
|
|
|
home match {
|
|
|
|
|
case None => ScalaInstance(version, launcher)
|
|
|
|
|
case Some(h) => ScalaInstance(h, launcher)
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-01 14:54:06 +01:00
|
|
|
|
2011-02-06 17:33:29 +01:00
|
|
|
lazy val testTasks = Seq(
|
2011-03-02 12:46:28 +01:00
|
|
|
testLoader <<= (fullClasspath, scalaInstance) map { (cp, si) => TestFramework.createTestLoader(data(cp), si) },
|
|
|
|
|
testFrameworks in GlobalScope :== {
|
2011-02-06 17:33:29 +01:00
|
|
|
import sbt.TestFrameworks._
|
|
|
|
|
Seq(ScalaCheck, Specs, ScalaTest, ScalaCheckCompat, ScalaTestCompat, SpecsCompat, JUnit)
|
|
|
|
|
},
|
2011-03-02 12:46:28 +01:00
|
|
|
loadedTestFrameworks <<= (testFrameworks, streams, testLoader) map { (frameworks, s, loader) =>
|
2011-02-06 17:33:29 +01:00
|
|
|
frameworks.flatMap(f => f.create(loader, s.log).map( x => (f,x)).toIterable).toMap
|
|
|
|
|
},
|
2011-03-02 12:46:28 +01:00
|
|
|
definedTests <<= (loadedTestFrameworks, compile, streams) map { (frameworkMap, analysis, s) =>
|
2011-03-05 14:25:17 +01:00
|
|
|
val tests = Tests.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
|
|
|
},
|
2011-03-02 12:46:28 +01:00
|
|
|
testListeners <<= (streams in test) map ( s => TestLogger(s.log) :: Nil ),
|
2011-03-05 14:25:17 +01:00
|
|
|
testOptions <<= testListeners map { listeners => Tests.Listeners(listeners) :: Nil },
|
2011-03-02 12:46:28 +01:00
|
|
|
executeTests <<= (streams in test, loadedTestFrameworks, testOptions, testLoader, definedTests) flatMap {
|
2011-03-05 14:25:17 +01:00
|
|
|
(s, frameworkMap, options, loader, discovered) => Tests(frameworkMap, loader, discovered, options, s.log)
|
2011-02-06 17:33:29 +01:00
|
|
|
},
|
2011-03-05 14:25:17 +01:00
|
|
|
test <<= (executeTests, streams) map { (results, s) => Tests.showResults(s.log, results) },
|
2011-03-02 12:46:28 +01:00
|
|
|
testOnly <<= testOnlyTask
|
2011-02-06 03:40:10 +01:00
|
|
|
)
|
|
|
|
|
|
2011-03-02 12:46:28 +01:00
|
|
|
def testOnlyTask =
|
2011-02-12 02:22:17 +01:00
|
|
|
InputTask(resolvedScoped(testOnlyParser)) ( result =>
|
2011-03-02 12:46:28 +01:00
|
|
|
(streams, loadedTestFrameworks, testOptions, testLoader, definedTests, result) flatMap {
|
2011-02-26 00:35:52 +01:00
|
|
|
case (s, frameworks, opts, loader, discovered, (tests, frameworkOptions)) =>
|
2011-03-05 14:25:17 +01:00
|
|
|
val modifiedOpts = Tests.Filter(if(tests.isEmpty) _ => true else tests.toSet ) +: Tests.Argument(frameworkOptions : _*) +: opts
|
|
|
|
|
Tests(frameworks, loader, discovered, modifiedOpts, s.log) map { results =>
|
|
|
|
|
Tests.showResults(s.log, results)
|
2011-02-12 02:22:17 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)
|
2011-02-10 14:16:07 +01:00
|
|
|
|
|
|
|
|
lazy val packageBase = Seq(
|
2011-03-02 12:46:28 +01:00
|
|
|
jarNameSetting,
|
|
|
|
|
packageOptions in GlobalScope :== Nil,
|
|
|
|
|
nameToString in GlobalScope :== (ArtifactName.show _)
|
2011-02-10 14:16:07 +01:00
|
|
|
)
|
|
|
|
|
lazy val packageConfig = Seq(
|
2011-03-02 12:46:28 +01:00
|
|
|
jarName <<= (jarName, configuration) { (n,c) => n.copy(config = c.name) },
|
|
|
|
|
packageOptions in packageBin <<= (packageOptions, mainClass in packageBin) map { _ ++ _.map(Package.MainClass.apply).toList }
|
2011-02-10 14:16:07 +01:00
|
|
|
) ++
|
2011-03-02 12:46:28 +01:00
|
|
|
packageTasks(packageBin, "", packageBinTask) ++
|
|
|
|
|
packageTasks(packageSrc, "src", packageSrcTask) ++
|
|
|
|
|
packageTasks(packageDoc, "doc", packageDocTask)
|
2011-02-10 14:16:07 +01:00
|
|
|
|
|
|
|
|
private[this] val allSubpaths = (_: File).###.***.xx.toSeq
|
|
|
|
|
|
2011-03-02 12:46:28 +01:00
|
|
|
def packageBinTask = concat(classMappings, resourceMappings)
|
|
|
|
|
def packageDocTask = doc map allSubpaths
|
|
|
|
|
def packageSrcTask = concat(resourceMappings, sourceMappings)
|
2011-02-24 01:19:44 +01:00
|
|
|
|
|
|
|
|
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 } )
|
2011-03-02 12:46:28 +01:00
|
|
|
def classMappings = (compileInputs, compile) map { (in, _) => allSubpaths(in.config.classesDirectory) }
|
2011-02-24 01:19:44 +01:00
|
|
|
// drop base directories, since there are no valid mappings for these
|
2011-03-02 12:46:28 +01:00
|
|
|
def sourceMappings = (sources, sourceDirectories, baseDirectory) map { (srcs, sdirs, base) =>
|
2011-02-24 01:19:44 +01:00
|
|
|
( (srcs --- sdirs --- base) x (relativeTo(sdirs)|relativeTo(base))) toSeq
|
|
|
|
|
}
|
2011-03-02 12:46:28 +01:00
|
|
|
def resourceMappings = (resources, resourceDirectories) map { (rs, rdirs) =>
|
2011-02-24 01:19:44 +01:00
|
|
|
(rs --- rdirs) x relativeTo(rdirs) toSeq
|
2011-02-10 14:16:07 +01:00
|
|
|
}
|
2011-02-24 01:19:44 +01:00
|
|
|
|
2011-03-02 12:46:28 +01:00
|
|
|
def jarNameSetting = jarName <<= (moduleID, version, scalaVersion, crossPaths) { (n,v, sv, withCross) =>
|
2011-02-21 16:22:39 +01:00
|
|
|
ArtifactName(base = n, version = v, config = "", tpe = "", ext = "jar", cross = if(withCross) sv else "")
|
2011-02-10 14:16:07 +01:00
|
|
|
}
|
2011-03-02 12:46:28 +01:00
|
|
|
def jarPathSetting = jarPath <<= (target, jarName, nameToString) { (t, n, toString) => t / toString(n) }
|
2011-02-10 14:16:07 +01:00
|
|
|
|
2011-03-02 12:46:28 +01:00
|
|
|
def packageTasks(key: TaskKey[Package.Configuration], tpeString: String, mappingsTask: Initialize[Task[Seq[(File,String)]]]) =
|
2011-02-10 14:16:07 +01:00
|
|
|
inTask(key)( Seq(
|
|
|
|
|
key in ThisScope.copy(task = Global) <<= packageTask,
|
2011-03-02 12:46:28 +01:00
|
|
|
mappings <<= mappingsTask,
|
|
|
|
|
jarType :== tpeString,
|
|
|
|
|
jarName <<= (jarType,jarName){ (tpe, name) => (name.copy(tpe = tpe)) },
|
|
|
|
|
cacheDirectory <<= cacheDirectory / key.key.label,
|
|
|
|
|
jarPathSetting
|
2011-02-10 14:16:07 +01:00
|
|
|
))
|
2011-03-02 12:46:28 +01:00
|
|
|
def packageTask: Initialize[Task[Package.Configuration]] =
|
|
|
|
|
(jarPath, mappings, packageOptions, cacheDirectory, streams) map { (jar, srcs, options, cacheDir, s) =>
|
|
|
|
|
val config = new Package.Configuration(srcs, jar, options)
|
|
|
|
|
Package(config, cacheDir, s.log)
|
2011-02-10 14:16:07 +01:00
|
|
|
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-03-02 12:46:28 +01:00
|
|
|
def runTask(classpath: ScopedTask[Classpath], mainClassTask: ScopedTask[Option[String]], scalaRun: ScopedSetting[ScalaRun]): Initialize[InputTask[Unit]] =
|
2011-02-12 02:22:17 +01:00
|
|
|
InputTask(_ => complete.Parsers.spaceDelimited("<arg>")) { result =>
|
2011-03-02 12:46:28 +01:00
|
|
|
(classpath, mainClassTask, scalaRun, 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-03-02 12:46:28 +01:00
|
|
|
def runnerSetting =
|
|
|
|
|
runner <<= (scalaInstance, baseDirectory, javaOptions, outputStrategy, fork, javaHome) { (si, base, options, strategy, forkRun, javaHomeDir) =>
|
|
|
|
|
if(forkRun) {
|
|
|
|
|
new ForkRun( ForkOptions(scalaJars = si.jars, javaHome = javaHomeDir, outputStrategy = strategy,
|
2011-02-26 00:35:52 +01:00
|
|
|
runJVMOptions = options, workingDirectory = Some(base)) )
|
|
|
|
|
} else
|
|
|
|
|
new Run(si)
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-12 02:22:17 +01:00
|
|
|
def docTask: Initialize[Task[File]] =
|
2011-03-02 12:46:28 +01:00
|
|
|
(compileInputs, streams, docDirectory, configuration, scaladocOptions) map { (in, s, target, config, options) =>
|
2011-02-06 17:33:29 +01:00
|
|
|
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-03-02 12:46:28 +01:00
|
|
|
def mainRunTask = run <<= runTask(fullClasspath in Configurations.Runtime, mainClass in run, runner in run)
|
2011-02-06 03:40:10 +01:00
|
|
|
|
2011-02-27 05:56:30 +01:00
|
|
|
def discoverMainClasses(analysis: inc.Analysis): Seq[String] =
|
2011-03-05 14:25:17 +01:00
|
|
|
Discovery.applications(Tests.allDefs(analysis)) collect { case (definition, discovered) if(discovered.hasMain) => definition.name }
|
2011-03-02 12:46:28 +01:00
|
|
|
|
2011-03-03 12:44:19 +01:00
|
|
|
def consoleProjectTask = (EvaluateTask.state, streams, initialCommands in consoleProject) map { (state, s, extra) => Console.sbt(state, extra)(s.log); println() }
|
2011-03-02 12:46:28 +01:00
|
|
|
def consoleTask: Initialize[Task[Unit]] = consoleTask(fullClasspath, console)
|
|
|
|
|
def consoleQuickTask = consoleTask(externalDependencyClasspath, consoleQuick)
|
|
|
|
|
def consoleTask(classpath: TaskKey[Classpath], task: TaskKey[_]): Initialize[Task[Unit]] = (compilers, classpath, scalacOptions in task, initialCommands in task, streams) map {
|
|
|
|
|
(cs, cp, options, initCommands, s) =>
|
|
|
|
|
(new Console(cs.scalac))(data(cp), options, initCommands, s.log).foreach(msg => error(msg))
|
2011-02-06 03:40:10 +01:00
|
|
|
println()
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-05 14:25:17 +01:00
|
|
|
def compileTask = (compileInputs, streams) map { (i,s) => Compiler(i,s.log) }
|
2011-02-03 13:17:47 +01:00
|
|
|
def compileInputsTask =
|
2011-03-10 00:04:53 +01:00
|
|
|
(dependencyClasspath, sources, compilers, javacOptions, scalacOptions, cacheDirectory, classDirectory, streams) map {
|
|
|
|
|
(cp, srcs, cs, javacOpts, scalacOpts, cacheDir, classes, s) =>
|
2011-02-03 13:17:47 +01:00
|
|
|
val classpath = classes +: data(cp)
|
|
|
|
|
val analysis = analysisMap(cp)
|
2011-03-02 12:46:28 +01:00
|
|
|
val cache = cacheDir / "compile"
|
2011-03-10 00:04:53 +01:00
|
|
|
Compiler.inputs(classpath, srcs, classes, scalacOpts, javacOpts, analysis, cache, 100)(cs, s.log)
|
2011-02-03 13:17:47 +01:00
|
|
|
}
|
|
|
|
|
|
2011-03-02 12:46:28 +01:00
|
|
|
def copyResourcesTask =
|
|
|
|
|
(classDirectory, cacheDirectory, resources, resourceDirectories, streams) map { (target, cache, resrcs, dirs, s) =>
|
2011-02-06 19:01:50 +01:00
|
|
|
val cacheFile = cache / "copy-resources"
|
2011-03-02 12:46:28 +01:00
|
|
|
val mappings = (resrcs --- 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
|
2011-03-02 12:46:28 +01:00
|
|
|
val tests = savedLines(state, resolved, definedTests)
|
2011-02-12 02:22:17 +01:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-01 14:54:06 +01:00
|
|
|
def inAllDependencies[T](base: ProjectRef, key: ScopedSetting[T], structure: Load.BuildStructure): Seq[T] =
|
|
|
|
|
{
|
|
|
|
|
def deps(ref: ProjectRef): Seq[ProjectRef] =
|
|
|
|
|
Project.getProject(ref, structure).toList.flatMap { p =>
|
|
|
|
|
p.dependencies.map(_.project) ++ p.aggregate
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inAllDeps(base, deps, key, structure.data)
|
|
|
|
|
}
|
|
|
|
|
def inAllDeps[T](base: ProjectRef, deps: ProjectRef => Seq[ProjectRef], key: ScopedSetting[T], data: Settings[Scope]): Seq[T] =
|
|
|
|
|
inAllProjects(Dag.topologicalSort(base)(deps), key, data)
|
2011-03-03 12:44:19 +01:00
|
|
|
def inAllProjects[T](allProjects: Seq[Reference], key: ScopedSetting[T], data: Settings[Scope]): Seq[T] =
|
2011-03-01 14:54:06 +01:00
|
|
|
allProjects.flatMap { p => key in p get data }
|
|
|
|
|
|
2011-02-12 02:22:17 +01:00
|
|
|
val CompletionsID = "completions"
|
2011-02-06 19:01:50 +01:00
|
|
|
|
2011-02-26 00:35:52 +01:00
|
|
|
lazy val defaultWebPaths = inConfig(CompileConf)(webPaths)
|
2011-02-21 16:07:58 +01:00
|
|
|
|
2011-03-03 12:44:19 +01:00
|
|
|
def noAggregation = Seq(run, console, consoleQuick, consoleProject)
|
2011-02-21 16:07:58 +01:00
|
|
|
lazy val disableAggregation = noAggregation map disableAggregate
|
|
|
|
|
def disableAggregate(k: Scoped) =
|
2011-03-02 12:46:28 +01:00
|
|
|
aggregate in Scope.GlobalScope.copy(task = Select(k.key)) :== false
|
2011-02-21 16:07:58 +01:00
|
|
|
|
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-27 22:28:00 +01:00
|
|
|
lazy val defaultSettings: Seq[Setting[_]] = projectCore ++ 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
|
2011-03-05 14:25:17 +01:00
|
|
|
import Defaults._
|
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-03-02 12:46:28 +01:00
|
|
|
externalDependencyClasspath <<= concat(unmanagedClasspath, managedClasspath),
|
|
|
|
|
dependencyClasspath <<= concat(internalDependencyClasspath, externalDependencyClasspath),
|
|
|
|
|
fullClasspath <<= concat(products, dependencyClasspath),
|
|
|
|
|
internalDependencyClasspath <<= internalDependencies,
|
|
|
|
|
unmanagedClasspath <<= unmanagedDependencies,
|
|
|
|
|
products <<= makeProducts,
|
|
|
|
|
managedClasspath <<= (configuration, update) map { (config, up) => up.getOrElse(config.name, error("Configuration '" + config.name + "' unresolved by 'update'.")) },
|
|
|
|
|
unmanagedJars <<= (configuration, 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[_]] =
|
2011-03-02 12:46:28 +01:00
|
|
|
for(task <- Seq(packageBin, `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-03-02 12:46:28 +01:00
|
|
|
publishMavenStyle in GlobalScope :== true,
|
|
|
|
|
packageToPublish <<= defaultPackageTasks.dependOn,
|
|
|
|
|
deliverDepends <<= (publishMavenStyle, makePom.setting, packageToPublish.setting) { (mavenStyle, mkpom, ptp) =>
|
|
|
|
|
if(mavenStyle) mkpom.map(_ => ()) else ptp
|
2011-02-12 02:22:17 +01:00
|
|
|
},
|
2011-03-02 12:46:28 +01:00
|
|
|
makePom <<= (ivyModule, makePomConfiguration, packageToPublish) map { (module, config, _) => IvyActions.makePom(module, config); config.file },
|
|
|
|
|
deliver <<= deliverTask(publishConfiguration),
|
|
|
|
|
deliverLocal <<= deliverTask(publishLocalConfiguration),
|
|
|
|
|
publish <<= publishTask(publishConfiguration, deliver),
|
|
|
|
|
publishLocal <<= publishTask(publishLocalConfiguration, deliverLocal)
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
2011-02-27 05:56:30 +01:00
|
|
|
val baseSettings: Seq[Setting[_]] = Seq(
|
2011-03-02 12:46:28 +01:00
|
|
|
unmanagedBase <<= baseDirectory / "lib",
|
|
|
|
|
normalizedName <<= name(StringUtilities.normalize),
|
|
|
|
|
organization :== normalizedName,
|
|
|
|
|
classpathFilter in GlobalScope :== "*.jar",
|
2011-03-10 00:04:53 +01:00
|
|
|
fullResolvers <<= (projectResolver,resolvers).map( (pr,rs) => pr +: Resolver.withDefaultResolvers(rs)),
|
2011-03-02 12:46:28 +01:00
|
|
|
offline in GlobalScope :== false,
|
|
|
|
|
moduleID :== normalizedName,
|
|
|
|
|
defaultConfiguration in GlobalScope :== Some(Configurations.Compile),
|
|
|
|
|
defaultConfigurationMapping in GlobalScope <<= defaultConfiguration{ case Some(d) => "*->" + d.name; case None => "*->*" },
|
2011-03-12 16:28:53 +01:00
|
|
|
ivyPaths <<= (baseDirectory, appConfiguration) { (base, app) => new IvyPaths(base, Option(app.provider.scalaProvider.launcher.ivyHome)) },
|
2011-03-02 12:46:28 +01:00
|
|
|
otherResolvers in GlobalScope :== Nil,
|
|
|
|
|
projectResolver <<= projectResolverTask,
|
|
|
|
|
projectDependencies <<= projectDependenciesTask,
|
|
|
|
|
libraryDependencies in GlobalScope :== Nil,
|
|
|
|
|
allDependencies <<= concat(projectDependencies,libraryDependencies),
|
|
|
|
|
ivyLoggingLevel in GlobalScope :== UpdateLogging.Quiet,
|
|
|
|
|
ivyXML in GlobalScope :== NodeSeq.Empty,
|
|
|
|
|
ivyValidate in GlobalScope :== false,
|
|
|
|
|
ivyScala in GlobalScope <<= scalaVersion(v => Some(new IvyScala(v, Nil, false, false))),
|
|
|
|
|
moduleConfigurations in GlobalScope :== Nil,
|
|
|
|
|
publishTo in GlobalScope :== None,
|
|
|
|
|
pomName <<= (moduleID, version, scalaVersion, crossPaths) { (n,v,sv, withCross) =>
|
2011-02-21 16:22:39 +01:00
|
|
|
ArtifactName(base = n, version = v, config = "", tpe = "", ext = "pom", cross = if(withCross) sv else "")
|
|
|
|
|
},
|
2011-03-02 12:46:28 +01:00
|
|
|
pomFile <<= (target, pomName, nameToString) { (t, n, toString) => t / toString(n) },
|
|
|
|
|
pomArtifact <<= (publishMavenStyle, moduleID)( (mavenStyle, name) => if(mavenStyle) Artifact(name, "pom", "pom") :: Nil else Nil),
|
|
|
|
|
artifacts <<= (pomArtifact,moduleID)( (pom,name) => Artifact(name) +: pom),
|
|
|
|
|
projectID <<= (organization,moduleID,version,artifacts){ (org,module,version,as) => ModuleID(org, module, version).cross(true).artifacts(as : _*) },
|
2011-03-10 00:04:53 +01:00
|
|
|
resolvers in GlobalScope :== Nil,
|
2011-03-02 12:46:28 +01:00
|
|
|
projectDescriptors <<= depMap,
|
|
|
|
|
retrievePattern :== "[type]/[organisation]/[module]/[artifact](-[revision])(-[classifier]).[ext]",
|
|
|
|
|
updateConfiguration <<= (retrieveConfiguration, ivyLoggingLevel)((conf,level) => new UpdateConfiguration(conf, level) ),
|
|
|
|
|
retrieveConfiguration :== None, //Some(new RetrieveConfiguration(managedDependencyPath asFile, retrievePattern, true))
|
2011-03-10 00:04:53 +01:00
|
|
|
ivyConfiguration <<= (fullResolvers, ivyPaths, otherResolvers, moduleConfigurations, offline, appConfiguration) map { (rs, paths, other, moduleConfs, off, app) =>
|
2011-02-03 13:17:47 +01:00
|
|
|
// todo: pass logger from streams directly to IvyActions
|
|
|
|
|
val lock = app.provider.scalaProvider.launcher.globalLock
|
2011-03-02 12:46:28 +01:00
|
|
|
new InlineIvyConfiguration(paths, rs, other, moduleConfs, off, Some(lock), ConsoleLogger())
|
2011-02-05 04:02:39 +01:00
|
|
|
},
|
2011-03-02 12:46:28 +01:00
|
|
|
moduleSettings <<= (projectID, allDependencies, ivyXML, thisProject, defaultConfiguration, ivyScala, ivyValidate) map {
|
|
|
|
|
(pid, deps, ivyXML, project, defaultConf, ivyS, validate) => new InlineConfiguration(pid, deps, ivyXML, project.configurations, defaultConf, ivyS, validate)
|
2011-02-05 04:02:39 +01:00
|
|
|
},
|
2011-03-02 12:46:28 +01:00
|
|
|
makePomConfiguration <<= pomFile(file => makePomConfigurationTask(file)),
|
|
|
|
|
publishConfiguration <<= (target, publishTo, ivyLoggingLevel) map { (outputDirectory, publishTo, level) => publishConfig( publishPatterns(outputDirectory), resolverName = getPublishTo(publishTo).name, logging = level) },
|
|
|
|
|
publishLocalConfiguration <<= (target, ivyLoggingLevel) map { (outputDirectory, level) => publishConfig( publishPatterns(outputDirectory, true), logging = level ) },
|
|
|
|
|
ivySbt <<= ivyConfiguration map { conf => new IvySbt(conf) },
|
|
|
|
|
ivyModule <<= (ivySbt, moduleSettings) map { (ivySbt, settings) => new ivySbt.Module(settings) },
|
|
|
|
|
update <<= (ivyModule, updateConfiguration, cacheDirectory, streams) map { (module, config, cacheDirectory, s) =>
|
|
|
|
|
cachedUpdate(cacheDirectory / "update", module, config, s.log)
|
2011-02-05 04:02:39 +01:00
|
|
|
}
|
2011-02-03 13:17:47 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2011-03-02 12:46:28 +01:00
|
|
|
def deliverTask(config: TaskKey[PublishConfiguration]): Initialize[Task[Unit]] =
|
|
|
|
|
(ivyModule, config, deliverDepends) map { (module, config, _) => IvyActions.deliver(module, config) }
|
|
|
|
|
def publishTask(config: TaskKey[PublishConfiguration], deliverKey: TaskKey[_]): Initialize[Task[Unit]] =
|
|
|
|
|
(ivyModule, config, deliverKey) map { (module, config, _) => IvyActions.publish(module, config) }
|
2011-02-03 13:17:47 +01:00
|
|
|
|
|
|
|
|
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)*/
|
|
|
|
|
}*/
|
2011-03-02 12:46:28 +01:00
|
|
|
def makePomConfigurationTask(file: File, configurations: Option[Iterable[Configuration]] = None, extra: NodeSeq = NodeSeq.Empty, process: XNode => XNode = n => n, filterRepositories: MavenRepository => Boolean = _ => true) =
|
2011-02-03 13:17:47 +01:00
|
|
|
new MakePomConfiguration(file, configurations, extra, process, filterRepositories)
|
|
|
|
|
|
|
|
|
|
def getPublishTo(repo: Option[Resolver]): Resolver = repo getOrElse error("Repository for publishing is not specified.")
|
|
|
|
|
|
2011-03-02 12:46:28 +01:00
|
|
|
def publishConfig(patterns: PublishPatterns, resolverName: String = "local", status: String = "release", logging: UpdateLogging.Value = UpdateLogging.DownloadOnly) =
|
2011-02-03 13:17:47 +01:00
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-02 12:46:28 +01:00
|
|
|
def projectDependenciesTask =
|
|
|
|
|
(thisProject, settings) map { (p, data) =>
|
|
|
|
|
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-03-02 12:46:28 +01:00
|
|
|
(thisProject, thisProjectRef, settings) flatMap { (root, rootRef, data) =>
|
2011-03-03 12:44:19 +01:00
|
|
|
val dependencies = (p: (ProjectRef, ResolvedProject)) => 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)
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-03 12:44:19 +01:00
|
|
|
def depMap(projects: Seq[(ProjectRef,ResolvedProject)], data: Settings[Scope]): Task[Map[ModuleRevisionId, ModuleDescriptor]] =
|
2011-03-02 12:46:28 +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-03-02 12:46:28 +01:00
|
|
|
def projectResolverTask: Initialize[Task[Resolver]] =
|
|
|
|
|
projectDescriptors map { m =>
|
2011-02-03 13:17:47 +01:00
|
|
|
new RawRepository(new ProjectResolver("inter-project", m))
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-02 12:46:28 +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-03-02 12:46:28 +01:00
|
|
|
(compile, 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-03-02 12:46:28 +01:00
|
|
|
(thisProjectRef, thisProject, configuration, settings) flatMap internalDependencies0
|
2011-02-20 05:25:30 +01:00
|
|
|
def unmanagedDependencies: Initialize[Task[Classpath]] =
|
2011-03-02 12:46:28 +01:00
|
|
|
(thisProjectRef, thisProject, configuration, settings) 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
|
2011-03-03 12:44:19 +01:00
|
|
|
def interSort(projectRef: ProjectRef, project: ResolvedProject, conf: Configuration, data: Settings[Scope]): Seq[(ProjectRef,String)] =
|
2011-02-03 13:17:47 +01:00
|
|
|
{
|
|
|
|
|
val visited = asScalaSet(new LinkedHashSet[(ProjectRef,String)])
|
2011-03-03 12:44:19 +01:00
|
|
|
def visit(p: ProjectRef, project: ResolvedProject, c: Configuration)
|
2011-02-03 13:17:47 +01:00
|
|
|
{
|
|
|
|
|
val applicableConfigs = allConfigs(c)
|
|
|
|
|
for(ac <- applicableConfigs) // add all configurations in this project
|
|
|
|
|
visited add (p, ac.name)
|
|
|
|
|
val masterConfs = configurationNames(project)
|
|
|
|
|
|
2011-03-03 12:44:19 +01:00
|
|
|
for( Project.ResolvedClasspathDependency(dep, confMapping) <- project.dependencies)
|
2011-02-03 13:17:47 +01:00
|
|
|
{
|
2011-03-02 12:46:28 +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))
|
|
|
|
|
{
|
2011-03-02 12:46:28 +01:00
|
|
|
val depConf = getConfiguration(dep, depProject, depConfName)
|
2011-02-03 13:17:47 +01:00
|
|
|
if( ! visited( (dep, depConfName) ) )
|
|
|
|
|
visit(dep, depProject, depConf)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
visit(projectRef, project, conf)
|
2011-02-20 05:25:30 +01:00
|
|
|
visited.toSeq
|
|
|
|
|
}
|
2011-03-03 12:44:19 +01:00
|
|
|
def unmanagedDependencies0(projectRef: ProjectRef, project: ResolvedProject, conf: Configuration, data: Settings[Scope]): Task[Classpath] =
|
2011-02-20 21:40:29 +01:00
|
|
|
interDependencies(projectRef, project, conf, data, true, unmanagedLibs)
|
2011-03-03 12:44:19 +01:00
|
|
|
def internalDependencies0(projectRef: ProjectRef, project: ResolvedProject, conf: Configuration, data: Settings[Scope]): Task[Classpath] =
|
2011-03-02 12:46:28 +01:00
|
|
|
interDependencies(projectRef, project, conf, data, false, productsTask)
|
2011-03-03 12:44:19 +01:00
|
|
|
def interDependencies(projectRef: ProjectRef, project: ResolvedProject, 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-03-03 12:44:19 +01:00
|
|
|
if(includeSelf || (dep != projectRef) || conf.name != c )
|
2011-02-20 21:40:29 +01:00
|
|
|
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;
|
|
|
|
|
|
2011-03-03 12:44:19 +01:00
|
|
|
def configurationNames(p: ResolvedProject): Seq[String] = p.configurations.map( _.name)
|
2011-02-03 13:17:47 +01:00
|
|
|
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)
|
|
|
|
|
|
2011-03-03 12:44:19 +01:00
|
|
|
def getConfiguration(ref: ProjectRef, dep: ResolvedProject, conf: String): Configuration =
|
2011-02-03 13:17:47 +01:00
|
|
|
dep.configurations.find(_.name == conf) getOrElse missingConfiguration(Project display ref, conf)
|
2011-03-03 12:44:19 +01:00
|
|
|
def productsTask(dep: ResolvedReference, conf: String, data: Settings[Scope]): Task[Classpath] =
|
2011-03-02 12:46:28 +01:00
|
|
|
getClasspath(products, dep, conf, data)
|
2011-03-03 12:44:19 +01:00
|
|
|
def unmanagedLibs(dep: ResolvedReference, conf: String, data: Settings[Scope]): Task[Classpath] =
|
2011-03-02 12:46:28 +01:00
|
|
|
getClasspath(unmanagedJars, dep, conf, data)
|
2011-03-03 12:44:19 +01:00
|
|
|
def getClasspath(key: TaskKey[Classpath], dep: ResolvedReference, conf: String, data: Settings[Scope]): Task[Classpath] =
|
2011-02-20 05:25:30 +01:00
|
|
|
( key in (dep, ConfigKey(conf)) ) get data getOrElse const(Nil)
|
2011-03-03 12:44:19 +01:00
|
|
|
def defaultConfigurationTask(p: ResolvedReference, data: Settings[Scope]): Configuration =
|
2011-03-02 12:46:28 +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
|
|
|
|
|
}
|