Merge pull request #3221 from eed3si9n/fport/3133

[fport] Port sbt-cross-building's ^ and ^^ commands
This commit is contained in:
eugene yokota 2017-05-27 01:12:00 -04:00 committed by GitHub
commit 4d3b910a19
20 changed files with 361 additions and 101 deletions

View File

@ -24,7 +24,7 @@ import sbt.librarymanagement.CrossVersion
object Cross { object Cross {
private def spacedFirst(name: String) = opOrIDSpaced(name) ~ any.+ private[sbt] def spacedFirst(name: String) = opOrIDSpaced(name) ~ any.+
private case class Switch(version: ScalaVersion, verbose: Boolean, command: Option[String]) private case class Switch(version: ScalaVersion, verbose: Boolean, command: Option[String])
private trait ScalaVersion { private trait ScalaVersion {
@ -77,7 +77,7 @@ object Cross {
private def crossRestoreSessionParser(state: State): Parser[String] = private def crossRestoreSessionParser(state: State): Parser[String] =
token(CrossRestoreSessionCommand) token(CrossRestoreSessionCommand)
private def requireSession[T](p: State => Parser[T]): State => Parser[T] = private[sbt] def requireSession[T](p: State => Parser[T]): State => Parser[T] =
s => if (s get sessionSettings isEmpty) failure("No project loaded") else p(s) s => if (s get sessionSettings isEmpty) failure("No project loaded") else p(s)
private def resolveAggregates(extracted: Extracted): Seq[ProjectRef] = { private def resolveAggregates(extracted: Extracted): Seq[ProjectRef] = {

View File

@ -218,6 +218,10 @@ object Defaults extends BuildCommon {
envVars :== Map.empty, envVars :== Map.empty,
sbtVersion := appConfiguration.value.provider.id.version, sbtVersion := appConfiguration.value.provider.id.version,
sbtBinaryVersion := binarySbtVersion(sbtVersion.value), sbtBinaryVersion := binarySbtVersion(sbtVersion.value),
// `pluginCrossBuild` scoping is based on sbt-cross-building plugin.
// The idea here is to be able to define a `sbtVersion in pluginCrossBuild`, which
// directs the dependencies of the plugin to build to the specified sbt plugin version.
sbtVersion in pluginCrossBuild := sbtVersion.value,
watchingMessage := Watched.defaultWatchingMessage, watchingMessage := Watched.defaultWatchingMessage,
triggeredMessage := Watched.defaultTriggeredMessage, triggeredMessage := Watched.defaultTriggeredMessage,
onLoad := idFun[State], onLoad := idFun[State],
@ -293,10 +297,16 @@ object Defaults extends BuildCommon {
sourceManaged := configSrcSub(sourceManaged).value, sourceManaged := configSrcSub(sourceManaged).value,
scalaSource := sourceDirectory.value / "scala", scalaSource := sourceDirectory.value / "scala",
javaSource := sourceDirectory.value / "java", javaSource := sourceDirectory.value / "java",
unmanagedSourceDirectories := makeCrossSources(scalaSource.value, unmanagedSourceDirectories := {
javaSource.value, makeCrossSources(scalaSource.value,
scalaBinaryVersion.value, javaSource.value,
crossPaths.value), scalaBinaryVersion.value,
crossPaths.value) ++
makePluginCrossSources(sbtPlugin.value,
scalaSource.value,
(sbtBinaryVersion in pluginCrossBuild).value,
crossPaths.value)
},
unmanagedSources := collectFiles(unmanagedSourceDirectories, unmanagedSources := collectFiles(unmanagedSourceDirectories,
includeFilter in unmanagedSources, includeFilter in unmanagedSources,
excludeFilter in unmanagedSources).value, excludeFilter in unmanagedSources).value,
@ -349,9 +359,22 @@ object Defaults extends BuildCommon {
), ),
scalaInstance := scalaInstanceTask.value, scalaInstance := scalaInstanceTask.value,
crossVersion := (if (crossPaths.value) CrossVersion.binary else Disabled()), crossVersion := (if (crossPaths.value) CrossVersion.binary else Disabled()),
scalaVersion := {
val scalaV = scalaVersion.value
val sv = (sbtBinaryVersion in pluginCrossBuild).value
val isPlugin = sbtPlugin.value
if (isPlugin) {
val x = scalaVersionFromSbtBinaryVersion(sv)
println(s"scalaVersionFromSbtBinaryVersion($sv) = $x")
x
} else scalaV
},
sbtBinaryVersion in pluginCrossBuild := binarySbtVersion(
(sbtVersion in pluginCrossBuild).value),
crossSbtVersions := Vector((sbtVersion in pluginCrossBuild).value),
crossTarget := makeCrossTarget(target.value, crossTarget := makeCrossTarget(target.value,
scalaBinaryVersion.value, scalaBinaryVersion.value,
sbtBinaryVersion.value, (sbtBinaryVersion in pluginCrossBuild).value,
sbtPlugin.value, sbtPlugin.value,
crossPaths.value), crossPaths.value),
clean := { clean := {
@ -359,6 +382,8 @@ object Defaults extends BuildCommon {
IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log) IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log)
}, },
scalaCompilerBridgeSource := { scalaCompilerBridgeSource := {
// This is a workaround for sbtVersion getting set to another value.
val sv = appConfiguration.value.provider.id.version
if (ScalaInstance.isDotty(scalaVersion.value)) if (ScalaInstance.isDotty(scalaVersion.value))
// Maintained at https://github.com/lampepfl/dotty/tree/master/sbt-bridge // Maintained at https://github.com/lampepfl/dotty/tree/master/sbt-bridge
ModuleID(scalaOrganization.value, "dotty-sbt-bridge", scalaVersion.value) ModuleID(scalaOrganization.value, "dotty-sbt-bridge", scalaVersion.value)
@ -382,6 +407,14 @@ object Defaults extends BuildCommon {
derive(scalaBinaryVersion := binaryScalaVersion(scalaVersion.value)) derive(scalaBinaryVersion := binaryScalaVersion(scalaVersion.value))
)) ))
private[sbt] def scalaVersionFromSbtBinaryVersion(sv: String): String =
VersionNumber(sv) match {
case VersionNumber(Seq(0, 12, _*), _, _) => "2.9.2"
case VersionNumber(Seq(0, 13, _*), _, _) => "2.10.6"
case VersionNumber(Seq(1, 0, _*), _, _) => "2.12.2"
case _ => sys.error(s"Unsupported sbt binary version: $sv")
}
def makeCrossSources(scalaSrcDir: File, def makeCrossSources(scalaSrcDir: File,
javaSrcDir: File, javaSrcDir: File,
sv: String, sv: String,
@ -392,6 +425,15 @@ object Defaults extends BuildCommon {
Seq(scalaSrcDir, javaSrcDir) Seq(scalaSrcDir, javaSrcDir)
} }
def makePluginCrossSources(isPlugin: Boolean,
scalaSrcDir: File,
sbtBinaryV: String,
cross: Boolean): Seq[File] = {
if (cross && isPlugin)
Vector(scalaSrcDir.getParentFile / s"${scalaSrcDir.name}-sbt-$sbtBinaryV")
else Vector()
}
def makeCrossTarget(t: File, sv: String, sbtv: String, plugin: Boolean, cross: Boolean): File = { def makeCrossTarget(t: File, sv: String, sbtv: String, plugin: Boolean, cross: Boolean): File = {
val scalaBase = if (cross) t / ("scala-" + sv) else t val scalaBase = if (cross) t / ("scala-" + sv) else t
if (plugin) scalaBase / ("sbt-" + sbtv) else scalaBase if (plugin) scalaBase / ("sbt-" + sbtv) else scalaBase
@ -1470,7 +1512,20 @@ object Defaults extends BuildCommon {
projectCore ++ disableAggregation ++ Seq( projectCore ++ disableAggregation ++ Seq(
// Missing but core settings // Missing but core settings
baseDirectory := thisProject.value.base, baseDirectory := thisProject.value.base,
target := baseDirectory.value / "target" target := baseDirectory.value / "target",
// Use (sbtVersion in pluginCrossBuild) to pick the sbt module to depend from the plugin.
// Because `sbtVersion in pluginCrossBuild` can be scoped to project level,
// this setting needs to be set here too.
sbtDependency in pluginCrossBuild := {
val app = appConfiguration.value
val id = app.provider.id
val sv = (sbtVersion in pluginCrossBuild).value
val scalaV = (scalaVersion in pluginCrossBuild).value
val binVersion = (scalaBinaryVersion in pluginCrossBuild).value
val cross = if (id.crossVersioned) CrossVersion.binary else Disabled()
val base = ModuleID(id.groupID, id.name, sv).withCrossVersion(cross)
CrossVersion(scalaV, binVersion)(base).withCrossVersion(Disabled())
}
) )
// build.sbt is treated a Scala source of metabuild, so to enable deprecation flag on build.sbt we set the option here. // build.sbt is treated a Scala source of metabuild, so to enable deprecation flag on build.sbt we set the option here.
lazy val deprecationSettings: Seq[Setting[_]] = lazy val deprecationSettings: Seq[Setting[_]] =
@ -1884,8 +1939,11 @@ object Classpaths {
allDependencies := { allDependencies := {
val base = projectDependencies.value ++ libraryDependencies.value val base = projectDependencies.value ++ libraryDependencies.value
val dependency = sbtDependency.value val dependency = sbtDependency.value
val isPlugin = sbtPlugin.value
val sbtdeps =
(sbtDependency in pluginCrossBuild).value.withConfigurations(Some(Provided.name))
val pluginAdjust = val pluginAdjust =
if (sbtPlugin.value) dependency.withConfigurations(Some(Provided.name)) +: base if (isPlugin) sbtdeps +: base
else base else base
val sbtOrg = scalaOrganization.value val sbtOrg = scalaOrganization.value
val version = scalaVersion.value val version = scalaVersion.value
@ -1919,8 +1977,8 @@ object Classpaths {
Def.setting { Def.setting {
if (sbtPlugin.value) if (sbtPlugin.value)
sbtPluginExtra(projectID.value, sbtPluginExtra(projectID.value,
(sbtBinaryVersion in update).value, (sbtBinaryVersion in pluginCrossBuild).value,
(scalaBinaryVersion in update).value) (scalaBinaryVersion in pluginCrossBuild).value)
else projectID.value else projectID.value
} }
private[sbt] def ivySbt0: Initialize[Task[IvySbt]] = private[sbt] def ivySbt0: Initialize[Task[IvySbt]] =
@ -1950,77 +2008,78 @@ object Classpaths {
transitiveClassifiers in updateSbtClassifiers ~= (_.filter(_ != DocClassifier)) transitiveClassifiers in updateSbtClassifiers ~= (_.filter(_ != DocClassifier))
)) ))
def sbtClassifiersTasks = def sbtClassifiersTasks =
sbtClassifiersGlobalDefaults ++ inTask(updateSbtClassifiers)( sbtClassifiersGlobalDefaults ++
Seq( inTask(updateSbtClassifiers)(
externalResolvers := { Seq(
val explicit = buildStructure.value externalResolvers := {
.units(thisProjectRef.value.build) val explicit = buildStructure.value
.unit .units(thisProjectRef.value.build)
.plugins .unit
.pluginData .plugins
.resolvers .pluginData
explicit orElse bootRepositories(appConfiguration.value) getOrElse externalResolvers.value .resolvers
}, explicit orElse bootRepositories(appConfiguration.value) getOrElse externalResolvers.value
ivyConfiguration := new InlineIvyConfiguration( },
ivyPaths.value, ivyConfiguration := new InlineIvyConfiguration(
externalResolvers.value.toVector, ivyPaths.value,
Vector.empty, externalResolvers.value.toVector,
Vector.empty, Vector.empty,
offline.value, Vector.empty,
Option(lock(appConfiguration.value)), offline.value,
checksums.value.toVector, Option(lock(appConfiguration.value)),
Some(target.value / "resolution-cache"), checksums.value.toVector,
UpdateOptions(), Some(crossTarget.value / "resolution-cache"),
streams.value.log UpdateOptions(),
), streams.value.log
ivySbt := ivySbt0.value, ),
classifiersModule := classifiersModuleTask.value, ivySbt := ivySbt0.value,
// Redefine scalaVersion and scalaBinaryVersion specifically for the dependency graph used for updateSbtClassifiers task. classifiersModule := classifiersModuleTask.value,
// to fix https://github.com/sbt/sbt/issues/2686 // Redefine scalaVersion and scalaBinaryVersion specifically for the dependency graph used for updateSbtClassifiers task.
scalaVersion := appConfiguration.value.provider.scalaProvider.version, // to fix https://github.com/sbt/sbt/issues/2686
scalaBinaryVersion := binaryScalaVersion(scalaVersion.value), scalaVersion := appConfiguration.value.provider.scalaProvider.version,
ivyScala := { scalaBinaryVersion := binaryScalaVersion(scalaVersion.value),
Some( ivyScala := {
IvyScala(scalaVersion.value, Some(
scalaBinaryVersion.value, IvyScala(scalaVersion.value,
Vector(), scalaBinaryVersion.value,
checkExplicit = false, Vector(),
filterImplicit = false, checkExplicit = false,
overrideScalaVersion = true).withScalaOrganization(scalaOrganization.value)) filterImplicit = false,
}, overrideScalaVersion = true).withScalaOrganization(scalaOrganization.value))
updateSbtClassifiers in TaskGlobal := (Def.task { },
val s = streams.value updateSbtClassifiers in TaskGlobal := (Def.task {
val is = ivySbt.value val s = streams.value
val mod = classifiersModule.value val is = ivySbt.value
val c = updateConfiguration.value val mod = classifiersModule.value
val app = appConfiguration.value val c = updateConfiguration.value
val srcTypes = sourceArtifactTypes.value val app = appConfiguration.value
val docTypes = docArtifactTypes.value val srcTypes = sourceArtifactTypes.value
val log = s.log val docTypes = docArtifactTypes.value
val out = is.withIvy(log)(_.getSettings.getDefaultIvyUserDir) val log = s.log
val uwConfig = (unresolvedWarningConfiguration in update).value val out = is.withIvy(log)(_.getSettings.getDefaultIvyUserDir)
val depDir = dependencyCacheDirectory.value val uwConfig = (unresolvedWarningConfiguration in update).value
val ivy = ivyScala.value val depDir = dependencyCacheDirectory.value
val st = state.value val ivy = ivyScala.value
withExcludes(out, mod.classifiers, lock(app)) { excludes => val st = state.value
val noExplicitCheck = ivy.map(_.withCheckExplicit(false)) withExcludes(out, mod.classifiers, lock(app)) { excludes =>
IvyActions.transitiveScratch( val noExplicitCheck = ivy.map(_.withCheckExplicit(false))
is, IvyActions.transitiveScratch(
"sbt", is,
GetClassifiersConfiguration(mod, "sbt",
excludes, GetClassifiersConfiguration(mod,
c.withArtifactFilter(c.artifactFilter.invert), excludes,
noExplicitCheck, c.withArtifactFilter(c.artifactFilter.invert),
srcTypes, noExplicitCheck,
docTypes), srcTypes,
uwConfig, docTypes),
LogicalClock(st.hashCode), uwConfig,
Some(depDir), LogicalClock(st.hashCode),
log Some(depDir),
) log
} )
} tag (Tags.Update, Tags.Network)).value }
)) ++ Seq(bootIvyConfiguration := (ivyConfiguration in updateSbtClassifiers).value) } tag (Tags.Update, Tags.Network)).value
)) ++ Seq(bootIvyConfiguration := (ivyConfiguration in updateSbtClassifiers).value)
def classifiersModuleTask: Initialize[Task[GetClassifiersModule]] = def classifiersModuleTask: Initialize[Task[GetClassifiersModule]] =
Def.task { Def.task {
@ -2433,7 +2492,7 @@ object Classpaths {
val (rs, other) = (fullResolvers.value.toVector, otherResolvers.value.toVector) val (rs, other) = (fullResolvers.value.toVector, otherResolvers.value.toVector)
val s = streams.value val s = streams.value
warnResolversConflict(rs ++: other, s.log) warnResolversConflict(rs ++: other, s.log)
val resCacheDir = target.value / "resolution-cache" val resCacheDir = crossTarget.value / "resolution-cache"
new InlineIvyConfiguration( new InlineIvyConfiguration(
ivyPaths.value, ivyPaths.value,
rs, rs,

View File

@ -201,6 +201,8 @@ object Keys {
val classpathOptions = SettingKey[ClasspathOptions]("classpath-options", "Configures handling of Scala classpaths.", DSetting) val classpathOptions = SettingKey[ClasspathOptions]("classpath-options", "Configures handling of Scala classpaths.", DSetting)
val discoveredSbtPlugins = TaskKey[PluginDiscovery.DiscoveredNames]("discovered-sbt-plugins", "The names of sbt plugin-related modules (modules that extend Build, Plugin, AutoPlugin) defined by this project.", CTask) val discoveredSbtPlugins = TaskKey[PluginDiscovery.DiscoveredNames]("discovered-sbt-plugins", "The names of sbt plugin-related modules (modules that extend Build, Plugin, AutoPlugin) defined by this project.", CTask)
val sbtPlugin = SettingKey[Boolean]("sbt-plugin", "If true, enables adding sbt as a dependency and auto-generation of the plugin descriptor file.", BMinusSetting) val sbtPlugin = SettingKey[Boolean]("sbt-plugin", "If true, enables adding sbt as a dependency and auto-generation of the plugin descriptor file.", BMinusSetting)
val pluginCrossBuild = TaskKey[Unit]("pluginCrossBuild", "Dummy task to scope `sbtVersion in pluginCrossBuild`, which gets used for plugin compilation.")
val crossSbtVersions = SettingKey[Seq[String]]("crossSbtVersions", "The versions of Sbt used when cross-building an sbt plugin.")
val printWarnings = TaskKey[Unit]("print-warnings", "Shows warnings from compilation, including ones that weren't printed initially.", BPlusTask) val printWarnings = TaskKey[Unit]("print-warnings", "Shows warnings from compilation, including ones that weren't printed initially.", BPlusTask)
val fileInputOptions = SettingKey[Seq[String]]("file-input-options", "Options that take file input, which may invalidate the cache.", CSetting) val fileInputOptions = SettingKey[Seq[String]]("file-input-options", "Options that take file input, which may invalidate the cache.", CSetting)
val scalaCompilerBridgeSource = SettingKey[ModuleID]("scala-compiler-bridge-source", "Configures the module ID of the sources of the compiler bridge.", CSetting) val scalaCompilerBridgeSource = SettingKey[ModuleID]("scala-compiler-bridge-source", "Configures the module ID of the sources of the compiler bridge.", CSetting)

View File

@ -150,6 +150,7 @@ object BuiltinCommands {
def ConsoleCommands: Seq[Command] = def ConsoleCommands: Seq[Command] =
Seq(ignore, exit, IvyConsole.command, setLogLevel, early, act, nop) Seq(ignore, exit, IvyConsole.command, setLogLevel, early, act, nop)
def ScriptCommands: Seq[Command] = def ScriptCommands: Seq[Command] =
Seq(ignore, exit, Script.command, setLogLevel, early, act, nop) Seq(ignore, exit, Script.command, setLogLevel, early, act, nop)
@ -175,6 +176,8 @@ object BuiltinCommands {
loadFailed, loadFailed,
Cross.crossBuild, Cross.crossBuild,
Cross.switchVersion, Cross.switchVersion,
PluginCross.pluginCross,
PluginCross.pluginSwitch,
Cross.crossRestoreSession, Cross.crossRestoreSession,
setOnFailure, setOnFailure,
clearOnFailure, clearOnFailure,

View File

@ -0,0 +1,76 @@
/* sbt -- Simple Build Tool
* Copyright 2011 Mark Harrah
* Copyright 2012 Johannes Rudolph
*
* This was basically copied from the sbt source code and then adapted to use
* `sbtVersion in pluginCrossBuild`.
*/
package sbt
import sbt.internal.util.complete.{ Parser, DefaultParsers }
import DefaultParsers._
import sbt.Keys._
import Project._
import Scope.GlobalScope
import Def.ScopedKey
import sbt.internal.Load
import sbt.internal.CommandStrings._
import Cross.{ spacedFirst, requireSession }
/**
* Module responsible for plugin cross building.
*/
private[sbt] object PluginCross {
lazy val pluginSwitch: Command = {
def switchParser(state: State): Parser[(String, String)] = {
val knownVersions = Nil
lazy val switchArgs = token(NotSpace.examples(knownVersions: _*)) ~ (token(
Space ~> matched(state.combinedParser)) ?? "")
lazy val nextSpaced = spacedFirst(PluginSwitchCommand)
token(PluginSwitchCommand ~ OptSpace) flatMap { _ =>
switchArgs & nextSpaced
}
}
def crossExclude(s: Def.Setting[_]): Boolean =
s.key match {
case ScopedKey(Scope(_, _, pluginCrossBuild.key, _), sbtVersion.key) => true
case _ => false
}
Command.arb(requireSession(switchParser), pluginSwitchHelp) {
case (state, (version, command)) =>
val x = Project.extract(state)
import x._
state.log.info(s"Setting `sbtVersion in pluginCrossBuild` to $version")
val add = (sbtVersion in GlobalScope in pluginCrossBuild :== version) :: Nil
val cleared = session.mergeSettings.filterNot(crossExclude)
val newStructure = Load.reapply(cleared ++ add, structure)
Project.setProject(session, newStructure, command :: state)
}
}
lazy val pluginCross: Command = {
def crossParser(state: State): Parser[String] =
token(PluginCrossCommand <~ OptSpace) flatMap { _ =>
token(
matched(state.combinedParser &
spacedFirst(PluginCrossCommand)))
}
def crossVersions(state: State): List[String] = {
val x = Project.extract(state)
import x._
((crossSbtVersions in currentRef) get structure.data getOrElse Nil).toList
}
Command.arb(requireSession(crossParser), pluginCrossHelp) {
case (state, command) =>
val x = Project.extract(state)
import x._
val versions = crossVersions(state)
val current = (sbtVersion in pluginCrossBuild)
.get(structure.data)
.map(PluginSwitchCommand + " " + _)
.toList
if (versions.isEmpty) command :: state
else versions.map(PluginSwitchCommand + " " + _ + " " + command) ::: current ::: state
}
}
}

View File

@ -373,4 +373,32 @@ $SwitchCommand [<scala-version>=]<scala-home>[!] [-v] [<command>]
See also `help $CrossCommand` See also `help $CrossCommand`
""" """
val PluginCrossCommand = "^"
val PluginSwitchCommand = "^^"
def pluginCrossHelp: Help = Help.more(PluginCrossCommand, PluginCrossDetailed)
def pluginSwitchHelp: Help = Help.more(PluginSwitchCommand, PluginSwitchDetailed)
def PluginCrossDetailed =
s"""$PluginCrossCommand <command>
Runs <command> for each sbt version specified for cross-building.
For each string in `crossSbtVersions` in the current project, this command sets the
`sbtVersion in pluginCrossBuild` of all projects to that version, reloads the build,
and executes <command>. When finished, it reloads the build with the original
Scala version.
See also `help $PluginSwitchCommand`
"""
def PluginSwitchDetailed =
s"""$PluginSwitchCommand <sbt-version> [<command>]
Changes the sbt version and runs a command.
Sets the `sbtVersion in pluginCrossBuild` of all projects to <sbt-version> and
reloads the build. If <command> is provided, it is then executed.
See also `help $CrossCommand`
"""
} }

View File

@ -0,0 +1,37 @@
### Improvements
- Ports sbt-cross-building's `^` and `^^` commands for plugin cross building. See below.
### sbt-cross-building
[@jrudolph][@jrudolph]'s sbt-cross-building is a plugin author's plugin.
It adds cross command `^` and sbtVersion switch command `^^`, similar to `+` and `++`,
but for switching between multiple sbt versions across major versions.
sbt 0.13.16 merges these commands into sbt because the feature it provides is useful as we migrate plugins to sbt 1.0.
To switch the `sbtVersion in pluginCrossBuild` from the shell use:
```
^^ 1.0.0-M5
```
Your plugin will now build with sbt 1.0.0-M5 (and its Scala version 2.12.2).
If you need to make changes specific to a sbt version, you can now include them into `src/main/scala-sbt-0.13`,
and `src/main/scala-sbt-1.0.0-M5`, where the binary sbt version number is used as postfix.
To run a command across multiple sbt versions, set:
```scala
crossSbtVersions := Vector("0.13.15", "1.0.0-M5")
```
Then, run:
```
^ compile
```
[@jrudolph]: https://github.com/jrudolph
[@eed3si9n]: https://github.com/eed3si9n

View File

@ -2,6 +2,8 @@ libraryDependencies += "log4j" % "log4j" % "1.2.16" % "compile"
autoScalaLibrary := false autoScalaLibrary := false
crossPaths := false
TaskKey[Unit]("check-last-update-time") := (streams map { (s) => TaskKey[Unit]("check-last-update-time") := (streams map { (s) =>
val fullUpdateOutput = s.cacheDirectory / "out" val fullUpdateOutput = s.cacheDirectory / "out"
val timeDiff = System.currentTimeMillis()-fullUpdateOutput.lastModified() val timeDiff = System.currentTimeMillis()-fullUpdateOutput.lastModified()

View File

@ -0,0 +1,24 @@
val baseSbt = "1.0"
lazy val root = (project in file("."))
.settings(
sbtPlugin := true,
TaskKey[Unit]("check") := {
val crossV = (sbtVersion in pluginCrossBuild).value
val sv = projectID.value.extraAttributes("e:scalaVersion")
assert(sbtVersion.value startsWith baseSbt, s"Wrong sbt version: ${sbtVersion.value}")
assert(sv == "2.12", s"Wrong e:scalaVersion: $sv")
assert(scalaBinaryVersion.value == "2.12", s"Wrong Scala binary version: ${scalaBinaryVersion.value}")
assert(crossV startsWith "1.0.", s"Wrong `sbtVersion in pluginCrossBuild`: $crossV")
},
TaskKey[Unit]("check2") := {
val crossV = (sbtVersion in pluginCrossBuild).value
val sv = projectID.value.extraAttributes("e:scalaVersion")
assert(sbtVersion.value startsWith baseSbt, s"Wrong sbt version: ${sbtVersion.value}")
assert(sv == "2.10", s"Wrong e:scalaVersion: $sv")
assert(scalaBinaryVersion.value == "2.10", s"Wrong Scala binary version: ${scalaBinaryVersion.value}")
assert(crossV startsWith "0.13", s"Wrong `sbtVersion in pluginCrossBuild`: $crossV")
}
)

View File

@ -0,0 +1,5 @@
> check
> ^^0.13.15
> check2

View File

@ -0,0 +1,6 @@
lazy val root = (project in file("."))
.settings(
sbtPlugin := true,
sbtVersion in pluginCrossBuild := "0.13.15",
resolvers += Resolver.typesafeIvyRepo("releases")
)

View File

@ -0,0 +1,2 @@
// folder mustn't be included
trait B

View File

@ -0,0 +1 @@
object Test extends A with B

View File

@ -0,0 +1,3 @@
// should fail because the project is building for
// 0.13.15 where E is not included
object ErrorTest extends E

View File

@ -0,0 +1,3 @@
> show pluginCrossBuild::sbtDependency
> compile
-> test:compile

View File

@ -1,11 +1,5 @@
scriptedSettings lazy val root = (project in file("."))
.settings(
scriptedSbt := sbtVersion.value sbtPlugin := true,
resolvers += Resolver.typesafeIvyRepo("releases")
sbtPlugin := true )
sbtVersion in Global := "0.13.0-Beta2"
scalaVersion in Global := "2.10.2-RC2"
offline := true

View File

@ -1,5 +1,7 @@
# This tests that this sbt scripted plugin can launch the next one # This tests that this sbt scripted plugin can launch the previous one
# It is currently disabled because there is no next plugin version
> ++2.10.6
> ^^0.13.16-M1
$ copy-file changes/A.scala src/sbt-test/a/b/A.scala $ copy-file changes/A.scala src/sbt-test/a/b/A.scala
> scripted > scripted

View File

@ -9,6 +9,7 @@ import sbt.internal.util.complete.{ Parser, DefaultParsers }
import sbt.internal.inc.classpath.ClasspathUtilities import sbt.internal.inc.classpath.ClasspathUtilities
import sbt.internal.inc.ModuleUtilities import sbt.internal.inc.ModuleUtilities
import java.lang.reflect.Method import java.lang.reflect.Method
import sbt.librarymanagement.CrossVersion.binarySbtVersion
object ScriptedPlugin extends AutoPlugin { object ScriptedPlugin extends AutoPlugin {
override def requires = plugins.JvmPlugin override def requires = plugins.JvmPlugin
@ -32,13 +33,23 @@ object ScriptedPlugin extends AutoPlugin {
import autoImport._ import autoImport._
override lazy val projectSettings = Seq( override lazy val projectSettings = Seq(
ivyConfigurations ++= Seq(scriptedConf, scriptedLaunchConf), ivyConfigurations ++= Seq(scriptedConf, scriptedLaunchConf),
scriptedSbt := sbtVersion.value, scriptedSbt := (sbtVersion in pluginCrossBuild).value,
sbtLauncher := getJars(scriptedLaunchConf).map(_.get.head).value, sbtLauncher := getJars(scriptedLaunchConf).map(_.get.head).value,
sbtTestDirectory := sourceDirectory.value / "sbt-test", sbtTestDirectory := sourceDirectory.value / "sbt-test",
libraryDependencies ++= Seq( libraryDependencies ++= {
"org.scala-sbt" %% "scripted-sbt" % scriptedSbt.value % scriptedConf.toString, binarySbtVersion(scriptedSbt.value) match {
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString case "0.13" =>
), Seq(
"org.scala-sbt" % "scripted-sbt" % scriptedSbt.value % scriptedConf.toString,
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString
)
case sv if sv startsWith "1.0." =>
Seq(
"org.scala-sbt" %% "scripted-sbt" % scriptedSbt.value % scriptedConf.toString,
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString
)
}
},
scriptedBufferLog := true, scriptedBufferLog := true,
scriptedClasspath := getJars(scriptedConf).value, scriptedClasspath := getJars(scriptedConf).value,
scriptedTests := scriptedTestsTask.value, scriptedTests := scriptedTestsTask.value,