mirror of https://github.com/sbt/sbt.git
addPluginSbtFile command
Fixes https://github.com/sbt/sbt/issues/1502 This adds `--addPluginSbtFile=<file>` command, which adds the given .sbt file to the plugin build. Using this mechanism editors or IDEs can start a build with required plugin. ``` $ cat /tmp/extra.sbt addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.7") $ sbt --addPluginSbtFile=/tmp/extra.sbt ... sbt:helloworld> plugins In file:/xxxx/hellotest/ ... sbtassembly.AssemblyPlugin: enabled in root ```
This commit is contained in:
parent
a6ae813b7c
commit
932f911483
|
|
@ -83,7 +83,8 @@ $HelpCommand <regular expression>
|
|||
List("-" + elem, "--" + elem)
|
||||
}
|
||||
(s.startsWith(EarlyCommand + "(") && s.endsWith(")")) ||
|
||||
(levelOptions contains s)
|
||||
(levelOptions contains s) ||
|
||||
(s.startsWith("-" + AddPluginSbtFileCommand) || s.startsWith("--" + AddPluginSbtFileCommand))
|
||||
}
|
||||
|
||||
val EarlyCommand = "early"
|
||||
|
|
@ -96,6 +97,14 @@ $HelpCommand <regular expression>
|
|||
The order is preserved between all early commands, so `sbt "early(a)" "early(b)"` executes `a` and `b` in order.
|
||||
"""
|
||||
|
||||
def addPluginSbtFileHelp = {
|
||||
val brief =
|
||||
(s"--$AddPluginSbtFileCommand=<file>", "Adds the given *.sbt file to the plugin build.")
|
||||
Help(brief)
|
||||
}
|
||||
|
||||
val AddPluginSbtFileCommand = "addPluginSbtFile"
|
||||
|
||||
def ReadCommand = "<"
|
||||
def ReadFiles = " file1 file2 ..."
|
||||
def ReadDetailed =
|
||||
|
|
|
|||
|
|
@ -66,15 +66,42 @@ object BasicCommands {
|
|||
private[this] def levelParser: Parser[String] =
|
||||
Iterator(Level.Debug, Level.Info, Level.Warn, Level.Error) map (l => token(l.toString)) reduce (_ | _)
|
||||
|
||||
private[this] def addPluginSbtFileParser: Parser[File] = {
|
||||
token(AddPluginSbtFileCommand) ~> (":" | "=" | Space) ~> (StringBasic).examples(
|
||||
"/some/extra.sbt"
|
||||
) map {
|
||||
new File(_)
|
||||
}
|
||||
}
|
||||
|
||||
private[this] def addPluginSbtFileStringParser: Parser[String] = {
|
||||
token(
|
||||
token(AddPluginSbtFileCommand) ~ (":" | "=" | Space) ~ (StringBasic)
|
||||
.examples("/some/extra.sbt") map {
|
||||
case s1 ~ s2 ~ s3 => s1 + s2 + s3
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private[this] def earlyParser: State => Parser[String] = (s: State) => {
|
||||
val p1 = token(EarlyCommand + "(") flatMap (_ => otherCommandParser(s) <~ token(")"))
|
||||
val p2 = token("-") flatMap (_ => levelParser)
|
||||
val p3 = token("--") flatMap (_ => levelParser)
|
||||
val p2 = (token("-") | token("--")) flatMap (_ => levelParser)
|
||||
val p3 = (token("-") | token("--")) flatMap (_ => addPluginSbtFileStringParser)
|
||||
p1 | p2 | p3
|
||||
}
|
||||
|
||||
private[this] def earlyHelp = Help(EarlyCommand, EarlyCommandBrief, EarlyCommandDetailed)
|
||||
|
||||
/**
|
||||
* Adds additional *.sbt to the plugin build.
|
||||
* This must be combined with early command as: --addPluginSbtFile=/tmp/extra.sbt
|
||||
*/
|
||||
def addPluginSbtFile: Command = Command.arb(_ => addPluginSbtFileParser, addPluginSbtFileHelp) {
|
||||
(s, extraSbtFile) =>
|
||||
val extraFiles = s.get(BasicKeys.extraMetaSbtFiles).toList.flatten
|
||||
s.put(BasicKeys.extraMetaSbtFiles, extraFiles :+ extraSbtFile)
|
||||
}
|
||||
|
||||
def help: Command = Command.make(HelpCommand, helpBrief, helpDetailed)(helpParser)
|
||||
|
||||
def helpParser(s: State): Parser[() => State] = {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@ object BasicKeys {
|
|||
"The location where command line history is persisted.",
|
||||
40
|
||||
)
|
||||
|
||||
val extraMetaSbtFiles = AttributeKey[Seq[File]](
|
||||
"extraMetaSbtFile",
|
||||
"Additional plugin.sbt files.",
|
||||
10000
|
||||
)
|
||||
|
||||
val shellPrompt = AttributeKey[State => String](
|
||||
"shell-prompt",
|
||||
"The function that constructs the command prompt from the current build state.",
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ object BuiltinCommands {
|
|||
setLogLevel,
|
||||
plugin,
|
||||
plugins,
|
||||
addPluginSbtFile,
|
||||
writeSbtVersion,
|
||||
notifyUsersAboutShell,
|
||||
shell,
|
||||
|
|
|
|||
|
|
@ -714,7 +714,8 @@ private[sbt] object Load {
|
|||
createRoot,
|
||||
uri,
|
||||
config.pluginManagement.context,
|
||||
Nil
|
||||
Nil,
|
||||
s.get(BasicKeys.extraMetaSbtFiles).getOrElse(Nil)
|
||||
)
|
||||
val loadedProjectsRaw = timed("Load.loadUnit: loadedProjectsRaw", log) {
|
||||
loadProjects(initialProjects, !hasRootAlreadyDefined)
|
||||
|
|
@ -844,7 +845,8 @@ private[sbt] object Load {
|
|||
makeOrDiscoverRoot: Boolean,
|
||||
buildUri: URI,
|
||||
context: PluginManagement.Context,
|
||||
generatedConfigClassFiles: Seq[File]
|
||||
generatedConfigClassFiles: Seq[File],
|
||||
extraSbtFiles: Seq[File]
|
||||
): LoadedProjects =
|
||||
/*timed(s"Load.loadTransitive(${ newProjects.map(_.id) })", log)*/ {
|
||||
// load all relevant configuration files (.sbt, as .scala already exists at this point)
|
||||
|
|
@ -869,7 +871,11 @@ private[sbt] object Load {
|
|||
val autoPlugins: Seq[AutoPlugin] =
|
||||
try plugins.detected.deducePluginsFromProject(p1, log)
|
||||
catch { case e: AutoPluginException => throw translateAutoPluginException(e, p) }
|
||||
val p2 = this.resolveProject(p1, autoPlugins, plugins, injectSettings, memoSettings, log)
|
||||
val extra =
|
||||
if (context.globalPluginProject) extraSbtFiles
|
||||
else Nil
|
||||
val p2 =
|
||||
this.resolveProject(p1, autoPlugins, plugins, injectSettings, memoSettings, extra, log)
|
||||
val projectLevelExtra =
|
||||
if (expand) autoPlugins flatMap {
|
||||
_.derivedProjects(p2) map { _.setProjectOrigin(ProjectOrigin.DerivedProject) }
|
||||
|
|
@ -888,7 +894,8 @@ private[sbt] object Load {
|
|||
(root, rest, files, generated)
|
||||
case DiscoveredProjects(None, rest, files, generated) => (p, rest, files, generated)
|
||||
}
|
||||
val (finalRoot, projectLevelExtra) = finalizeProject(root, files, true)
|
||||
val (finalRoot, projectLevelExtra) =
|
||||
finalizeProject(root, files, true)
|
||||
(finalRoot, discovered ++ projectLevelExtra, generated)
|
||||
}
|
||||
|
||||
|
|
@ -910,11 +917,16 @@ private[sbt] object Load {
|
|||
false,
|
||||
buildUri,
|
||||
context,
|
||||
generated ++ generatedConfigClassFiles
|
||||
generated ++ generatedConfigClassFiles,
|
||||
Nil
|
||||
)
|
||||
case Nil if makeOrDiscoverRoot =>
|
||||
log.debug(s"[Loading] Scanning directory ${buildBase}")
|
||||
discover(AddSettings.defaultSbtFiles, buildBase) match {
|
||||
val auto =
|
||||
if (context.globalPluginProject)
|
||||
AddSettings.seq(AddSettings.defaultSbtFiles, AddSettings.sbtFiles(extraSbtFiles: _*))
|
||||
else AddSettings.defaultSbtFiles
|
||||
discover(auto, buildBase) match {
|
||||
case DiscoveredProjects(Some(root), discovered, files, generated) =>
|
||||
log.debug(
|
||||
s"[Loading] Found root project ${root.id} w/ remaining ${discovered.map(_.id).mkString(",")}"
|
||||
|
|
@ -935,7 +947,8 @@ private[sbt] object Load {
|
|||
false,
|
||||
buildUri,
|
||||
context,
|
||||
generated ++ generatedConfigClassFiles
|
||||
generated ++ generatedConfigClassFiles,
|
||||
Nil
|
||||
)
|
||||
// Here we need to create a root project...
|
||||
case DiscoveredProjects(None, discovered, files, generated) =>
|
||||
|
|
@ -953,6 +966,7 @@ private[sbt] object Load {
|
|||
false,
|
||||
buildUri,
|
||||
context,
|
||||
Nil,
|
||||
Nil
|
||||
)
|
||||
val otherGenerated = otherProjects.generatedConfigClassFiles
|
||||
|
|
@ -1014,6 +1028,7 @@ private[sbt] object Load {
|
|||
* @param globalUserSettings All the settings contributed from the ~/.sbt/<version> directory
|
||||
* @param memoSettings A recording of all loaded files (our files should reside in there). We should need not load any
|
||||
* sbt file to resolve a project.
|
||||
* @param extraSbtFiles Extra *.sbt files.
|
||||
* @param log A logger to report auto-plugin issues to.
|
||||
*/
|
||||
private[sbt] def resolveProject(
|
||||
|
|
@ -1022,6 +1037,7 @@ private[sbt] object Load {
|
|||
loadedPlugins: LoadedPlugins,
|
||||
globalUserSettings: InjectSettings,
|
||||
memoSettings: mutable.Map[File, LoadedSbtFile],
|
||||
extraSbtFiles: Seq[File],
|
||||
log: Logger
|
||||
): Project =
|
||||
timed(s"Load.resolveProject(${p.id})", log) {
|
||||
|
|
@ -1060,7 +1076,17 @@ private[sbt] object Load {
|
|||
b ++ expandSettings(add)
|
||||
}
|
||||
}
|
||||
expandSettings(AddSettings.allDefaults)
|
||||
val auto =
|
||||
if (extraSbtFiles.nonEmpty)
|
||||
AddSettings.seq(
|
||||
AddSettings.autoPlugins,
|
||||
AddSettings.buildScalaFiles,
|
||||
AddSettings.userSettings,
|
||||
AddSettings.defaultSbtFiles,
|
||||
AddSettings.sbtFiles(extraSbtFiles: _*),
|
||||
)
|
||||
else AddSettings.allDefaults
|
||||
expandSettings(auto)
|
||||
}
|
||||
// Finally, a project we can use in buildStructure.
|
||||
p.copy(settings = allSettings)
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ object SettingQueryTest extends org.specs2.mutable.Specification {
|
|||
loadedPlugins,
|
||||
injectSettings,
|
||||
fileToLoadedSbtFileMap,
|
||||
Nil,
|
||||
state.log
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
Adds `--addPluginSbtFile=<file>` command, which adds the given .sbt file to the plugin build.
|
||||
Using this mechanism editors or IDEs can start a build with required plugin.
|
||||
|
||||
```
|
||||
$ cat /tmp/extra.sbt
|
||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.7")
|
||||
|
||||
$ sbt --addPluginSbtFile=/tmp/extra.sbt
|
||||
...
|
||||
sbt:helloworld> plugins
|
||||
In file:/xxxx/hellotest/
|
||||
...
|
||||
sbtassembly.AssemblyPlugin: enabled in root
|
||||
```
|
||||
Loading…
Reference in New Issue