diff --git a/main/Build.scala b/main/Build.scala index 1a38a67f1..47be0acd6 100644 --- a/main/Build.scala +++ b/main/Build.scala @@ -488,7 +488,7 @@ object Load } def plugins(dir: File, s: State, config: LoadBuildConfiguration): LoadedPlugins = if(dir.exists) buildPlugins(dir, s, config) else noPlugins(dir, config) - def noPlugins(dir: File, config: LoadBuildConfiguration): LoadedPlugins = new LoadedPlugins(dir, config.classpath, config.loader, Nil, Nil) + def noPlugins(dir: File, config: LoadBuildConfiguration): LoadedPlugins = new LoadedPlugins(dir, config.classpath, config.loader, Nil, binaryPlugins(config.loader)) def buildPlugins(dir: File, s: State, config: LoadBuildConfiguration): LoadedPlugins = { val (eval,pluginDef) = apply(dir, s, config) @@ -525,11 +525,16 @@ object Load def loadPlugins(dir: File, classpath: Seq[File], loader: ClassLoader, analysis: Seq[inc.Analysis]): LoadedPlugins = { val (pluginNames, plugins) = if(classpath.isEmpty) (Nil, Nil) else { - val names = analysis flatMap findPlugins + val names = ( binaryPlugins(loader) ++ (analysis flatMap findPlugins) ).distinct (names, loadPlugins(loader, names) ) } new LoadedPlugins(dir, classpath, loader, plugins, pluginNames) } + def binaryPlugins(loader: ClassLoader): Seq[String] = + { + import collection.JavaConversions._ + loader.getResources("sbt/sbt.plugins").toSeq flatMap { u => IO.readLinesURL(u) map { _.trim } filter { !_.isEmpty } }; + } def loadPlugins(loader: ClassLoader, pluginNames: Seq[String]): Seq[Setting[_]] = pluginNames.flatMap(pluginName => loadPlugin(pluginName, loader)) diff --git a/main/Defaults.scala b/main/Defaults.scala index ec88d1649..bbccc912b 100755 --- a/main/Defaults.scala +++ b/main/Defaults.scala @@ -3,7 +3,6 @@ */ package sbt - import java.io.File import Build.data import Scope.{GlobalScope, ThisScope} import compiler.Discovery @@ -12,16 +11,20 @@ package sbt import EvaluateTask.{resolvedScoped, streams} import complete._ import std.TaskExtra._ + import scala.xml.{Node => XNode,NodeSeq} import org.apache.ivy.core.module.{descriptor, id} import descriptor.ModuleDescriptor, id.ModuleRevisionId - import Types._ + import java.io.File + import java.net.URL -object Defaults -{ + import Types._ import Path._ import GlobFilter._ import Keys._ + +object Defaults +{ implicit def richFileSetting(s: ScopedSetting[File]): RichFileSetting = new RichFileSetting(s) implicit def richFilesSetting(s: ScopedSetting[Seq[File]]): RichFilesSetting = new RichFilesSetting(s) @@ -61,7 +64,9 @@ object Defaults outputStrategy :== None, fork :== false, javaOptions :== Nil, + sbtPlugin :== false, crossPaths :== true, + generatedResources :== Nil, // shellPrompt :== (_ => "> "), aggregate :== Aggregation.Enabled, maxErrors :== 100, @@ -96,18 +101,16 @@ object Defaults scalaSource <<= sourceDirectory / "scala", javaSource <<= sourceDirectory / "java", resourceDirectory <<= sourceDirectory / "resources", + generatedResourceDirectory <<= target / "res_managed", sourceDirectories <<= (scalaSource, javaSource) { _ :: _ :: Nil }, - resourceDirectories <<= toSeq(resourceDirectory), - resources <<= (resourceDirectories, defaultExcludes) map { (dirs, excl) => dirs.descendentsExcept("*",excl).getFiles.toSeq } + resourceDirectories <<= (resourceDirectory, generatedResourceDirectory) { _ :: _ :: Nil }, + resources <<= (resourceDirectories, defaultExcludes, generatedResources, generatedResourceDirectory) map resourcesTask, + generatedResources <<= (definedSbtPlugins, generatedResourceDirectory) map writePluginsDescriptor ) def addBaseSources = Seq( sources <<= (sources, baseDirectory, sourceFilter, defaultExcludes) map { (srcs,b,f,excl) => (srcs +++ b * (f -- excl)).getFiles.toSeq } ) - def webPaths = Seq( - webappDir <<= sourceDirectory / "webapp" - ) - def compileBase = Seq( classpathOptions in GlobalScope :== ClasspathOptions.auto, compilers <<= (scalaInstance, appConfiguration, streams, classpathOptions, javaHome) map { (si, app, s, co, jh) => Compiler.compilers(si, co, jh)(app, s.log) }, @@ -125,6 +128,7 @@ object Defaults console <<= consoleTask, consoleQuick <<= consoleQuickTask, discoveredMainClasses <<= compile map discoverMainClasses, + definedSbtPlugins <<= discoverPlugins, inTask(run)(runnerSetting :: Nil).head, selectMainClass <<= discoveredMainClasses map selectRunMain, mainClass in run :== selectMainClass, @@ -172,6 +176,7 @@ object Defaults case Some(h) => ScalaInstance(h, launcher) } } + def resourcesTask(dirs: Seq[File], excl: FileFilter, gen: Seq[File], genDir: File) = gen ++ (dirs --- genDir).descendentsExcept("*",excl).getFiles lazy val testTasks = Seq( testLoader <<= (fullClasspath, scalaInstance) map { (cp, si) => TestFramework.createTestLoader(data(cp), si) }, @@ -206,7 +211,7 @@ object Defaults } } ) - + lazy val packageBase = Seq( jarNameSetting, packageOptions in GlobalScope :== Nil, @@ -311,6 +316,28 @@ object Defaults Compiler.inputs(classpath, srcs, classes, scalacOpts, javacOpts, analysis, cache, 100)(cs, s.log) } + def writePluginsDescriptor(plugins: Set[String], dir: File): List[File] = + { + val descriptor: File = dir / "sbt" / "sbt.plugins" + if(plugins.isEmpty) + { + IO.delete(descriptor) + Nil + } + else + { + IO.writeLines(descriptor, plugins.toSeq) + descriptor :: Nil + } + } + def discoverPlugins: Initialize[Task[Set[String]]] = (compile, sbtPlugin, streams) map { (analysis, isPlugin, s) => if(isPlugin) discoverSbtPlugins(analysis, s.log) else Set.empty } + def discoverSbtPlugins(analysis: inc.Analysis, log: Logger): Set[String] = + { + val pluginClass = classOf[Plugin].getName + val discovery = Discovery(Set(pluginClass), Set.empty)( Tests allDefs analysis ) + discovery collect { case (df, disc) if (disc.baseClasses contains pluginClass) && disc.isModule => df.name } toSet; + } + def copyResourcesTask = (classDirectory, cacheDirectory, resources, resourceDirectories, streams) map { (target, cache, resrcs, dirs, s) => val cacheFile = cache / "copy-resources" @@ -357,7 +384,6 @@ object Defaults val CompletionsID = "completions" - lazy val defaultWebPaths = inConfig(CompileConf)(webPaths) def noAggregation = Seq(run, console, consoleQuick, consoleProject) lazy val disableAggregation = noAggregation map disableAggregate @@ -366,8 +392,6 @@ object Defaults lazy val baseTasks: Seq[Setting[_]] = projectTasks ++ packageBase - lazy val defaultWebTasks = Nil - lazy val baseClasspaths = Classpaths.publishSettings ++ Classpaths.baseSettings lazy val configSettings = Classpaths.configSettings ++ configTasks ++ configPaths ++ packageConfig @@ -378,7 +402,6 @@ object Defaults lazy val defaultConfigs = inConfig(CompileConf)(compileSettings) ++ inConfig(TestConf)(testSettings) lazy val defaultSettings: Seq[Setting[_]] = projectCore ++ paths ++ baseClasspaths ++ baseTasks ++ compileBase ++ defaultConfigs ++ disableAggregation - lazy val defaultWebSettings = defaultSettings ++ defaultWebPaths ++ defaultWebTasks } object Classpaths { diff --git a/main/Keys.scala b/main/Keys.scala index 3a889eb13..9765be12b 100644 --- a/main/Keys.scala +++ b/main/Keys.scala @@ -73,8 +73,8 @@ object Keys val scalaInstance = SettingKey[ScalaInstance]("scala-instance") val scalaVersion = SettingKey[String]("scala-version") val classpathOptions = SettingKey[ClasspathOptions]("classpath-options") - - val webappDir = SettingKey[File]("webapp-dir") + val definedSbtPlugins = TaskKey[Set[String]]("defined-sbt-plugins") + val sbtPlugin = SettingKey[Boolean]("sbt-plugin") val clean = TaskKey[Unit]("clean") val console = TaskKey[Unit]("console") @@ -86,7 +86,10 @@ object Keys val copyResources = TaskKey[Traversable[(File,File)]]("copy-resources") val resources = TaskKey[Seq[File]]("resources") val aggregate = SettingKey[Aggregation]("aggregate") - + val generatedResources = TaskKey[Seq[File]]("generated-resources") + val generatedResourceDirectory = SettingKey[File]("generated-resource-directory") + + // package keys val packageBin = TaskKey[Package.Configuration]("package") val packageDoc = TaskKey[Package.Configuration]("package-doc")