diff --git a/main/src/main/scala/sbt/CommandStrings.scala b/main/src/main/scala/sbt/CommandStrings.scala index cb21d3053..3fd936d04 100644 --- a/main/src/main/scala/sbt/CommandStrings.scala +++ b/main/src/main/scala/sbt/CommandStrings.scala @@ -326,4 +326,32 @@ $SwitchCommand [=] [] 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 + Runs 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 . When finished, it reloads the build with the original + Scala version. + + See also `help $PluginSwitchCommand` +""" + + def PluginSwitchDetailed = + s"""$PluginSwitchCommand [] + Changes the sbt version and runs a command. + + Sets the `sbtVersion in pluginCrossBuild` of all projects to and + reloads the build. If is provided, it is then executed. + + See also `help $CrossCommand` +""" } diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index b943d5a17..3cee12cd1 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -136,6 +136,10 @@ object Defaults extends BuildCommon { envVars :== Map.empty, sbtVersion := appConfiguration.value.provider.id.version, 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, triggeredMessage := Watched.defaultTriggeredMessage, onLoad := idFun[State], @@ -190,7 +194,16 @@ object Defaults extends BuildCommon { sourceManaged := configSrcSub(sourceManaged).value, scalaSource := sourceDirectory.value / "scala", javaSource := sourceDirectory.value / "java", - unmanagedSourceDirectories := makeCrossSources(scalaSource.value, javaSource.value, scalaBinaryVersion.value, crossPaths.value), + unmanagedSourceDirectories := { + makeCrossSources(scalaSource.value, + javaSource.value, + scalaBinaryVersion.value, + crossPaths.value) ++ + makePluginCrossSources(sbtPlugin.value, + scalaSource.value, + (sbtBinaryVersion in pluginCrossBuild).value, + crossPaths.value) + }, unmanagedSources := collectFiles(unmanagedSourceDirectories, includeFilter in unmanagedSources, excludeFilter in unmanagedSources).value, watchSources in ConfigGlobal ++= unmanagedSources.value, managedSourceDirectories := Seq(sourceManaged.value), @@ -231,17 +244,31 @@ object Defaults extends BuildCommon { sbt.inc.ClassfileManager.transactional(crossTarget.value / "classes.bak", sbt.Logger.Null)), scalaInstance := scalaInstanceTask.value, crossVersion := (if (crossPaths.value) CrossVersion.binary else CrossVersion.Disabled), - crossTarget := makeCrossTarget(target.value, scalaBinaryVersion.value, sbtBinaryVersion.value, sbtPlugin.value, crossPaths.value), + scalaVersion := { + val scalaV = scalaVersion.value + val sv = (sbtBinaryVersion in pluginCrossBuild).value + if (sbtPlugin.value) scalaVersionFromSbtBinaryVersion(sv) + else scalaV + }, + sbtBinaryVersion in pluginCrossBuild := binarySbtVersion((sbtVersion in pluginCrossBuild).value), + crossSbtVersions := Vector((sbtVersion in pluginCrossBuild).value), + crossTarget := makeCrossTarget(target.value, + scalaBinaryVersion.value, + (sbtBinaryVersion in pluginCrossBuild).value, + sbtPlugin.value, + crossPaths.value), clean := { val _ = clean.value IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log) }, scalaCompilerBridgeSource := { + // This is a workaround for sbtVersion getting set to another value. + val sv = appConfiguration.value.provider.id.version if (ScalaInstance.isDotty(scalaVersion.value)) // Maintained at https://github.com/lampepfl/dotty/tree/master/sbt-bridge ModuleID(scalaOrganization.value, "dotty-sbt-bridge", scalaVersion.value, Some("component")).sources() else - ModuleID(xsbti.ArtifactInfo.SbtOrganization, "compiler-interface", sbtVersion.value, Some("component")).sources() + ModuleID(xsbti.ArtifactInfo.SbtOrganization, "compiler-interface", sv, Some("component")).sources() } ) // must be a val: duplication detected by object identity @@ -258,6 +285,14 @@ object Defaults extends BuildCommon { 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, javaSrcDir: File, sv: String, cross: Boolean): Seq[File] = { if (cross) Seq(scalaSrcDir.getParentFile / s"${scalaSrcDir.name}-$sv", scalaSrcDir, javaSrcDir) @@ -265,6 +300,12 @@ object Defaults extends BuildCommon { 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 = { val scalaBase = if (cross) t / ("scala-" + sv) else t @@ -1033,7 +1074,20 @@ object Defaults extends BuildCommon { projectCore ++ disableAggregation ++ Seq( // Missing but core settings 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 CrossVersion.Disabled + val base = ModuleID(id.groupID, id.name, sv, crossVersion = cross) + CrossVersion(scalaV, binVersion)(base).copy(crossVersion = CrossVersion.Disabled) + } ) // 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[_]] = @@ -1301,7 +1355,7 @@ object Classpaths { // Override the default to handle mixing in the sbtPlugin + scala dependencies. allDependencies := { val base = projectDependencies.value ++ libraryDependencies.value - val pluginAdjust = if (sbtPlugin.value) sbtDependency.value.copy(configurations = Some(Provided.name)) +: base else base + val pluginAdjust = if (sbtPlugin.value) (sbtDependency in pluginCrossBuild).value.copy(configurations = Some(Provided.name)) +: base else base if (scalaHome.value.isDefined || ivyScala.value.isEmpty || !managedScalaInstance.value) pluginAdjust else { @@ -1328,11 +1382,14 @@ object Classpaths { case _ => base } } - - def pluginProjectID: Initialize[ModuleID] = (sbtBinaryVersion in update, scalaBinaryVersion in update, projectID, sbtPlugin) { - (sbtBV, scalaBV, pid, isPlugin) => - if (isPlugin) sbtPluginExtra(pid, sbtBV, scalaBV) else pid - } + def pluginProjectID: Initialize[ModuleID] = + Def.setting { + if (sbtPlugin.value) + sbtPluginExtra(projectID.value, + (sbtBinaryVersion in pluginCrossBuild).value, + (scalaBinaryVersion in pluginCrossBuild).value) + else projectID.value + } def ivySbt0: Initialize[Task[IvySbt]] = (ivyConfiguration, credentials, streams) map { (conf, creds, s) => Credentials.register(creds, s.log) @@ -1351,8 +1408,18 @@ object Classpaths { val explicit = buildStructure.value.units(thisProjectRef.value.build).unit.plugins.pluginData.resolvers explicit orElse bootRepositories(appConfiguration.value) getOrElse externalResolvers.value }, - ivyConfiguration := new InlineIvyConfiguration(ivyPaths.value, externalResolvers.value, Nil, Nil, offline.value, Option(lock(appConfiguration.value)), - checksums.value, Some(target.value / "resolution-cache"), UpdateOptions(), streams.value.log), + ivyConfiguration := new InlineIvyConfiguration( + ivyPaths.value, + externalResolvers.value.toVector, + Vector.empty, + Vector.empty, + offline.value, + Option(lock(appConfiguration.value)), + checksums.value.toVector, + Some(crossTarget.value / "resolution-cache"), + UpdateOptions(), + streams.value.log + ), ivySbt := ivySbt0.value, classifiersModule := ((projectID, sbtDependency, transitiveClassifiers, loadedBuild, thisProjectRef) map { (pid, sbtDep, classifiers, lb, ref) => val pluginClasspath = lb.units(ref.build).unit.plugins.fullClasspath @@ -1695,13 +1762,24 @@ object Classpaths { def unmanagedDependencies: Initialize[Task[Classpath]] = (thisProjectRef, configuration, settingsData, buildDependencies) flatMap unmanagedDependencies0 def mkIvyConfiguration: Initialize[Task[IvyConfiguration]] = - (fullResolvers, ivyPaths, otherResolvers, moduleConfigurations, offline, checksums in update, appConfiguration, - target, updateOptions, streams) map { (rs, paths, other, moduleConfs, off, check, app, t, uo, s) => - warnResolversConflict(rs ++: other, s.log) - val resCacheDir = t / "resolution-cache" - - new InlineIvyConfiguration(paths, rs, other, moduleConfs, off, Option(lock(app)), check, Some(resCacheDir), uo, s.log) - } + Def.task { + val (rs, other) = (fullResolvers.value.toVector, otherResolvers.value.toVector) + val s = streams.value + warnResolversConflict(rs ++: other, s.log) + val resCacheDir = crossTarget.value / "resolution-cache" + new InlineIvyConfiguration( + ivyPaths.value, + rs, + other, + moduleConfigurations.value.toVector, + offline.value, + Option(lock(appConfiguration.value)), + (checksums in update).value.toVector, + Some(resCacheDir), + updateOptions.value, + s.log + ) + } import java.util.LinkedHashSet import collection.JavaConversions.asScalaSet diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index fe88af999..fd75b43ba 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -137,6 +137,8 @@ object Keys { val definedSbtPlugins = TaskKey[Set[String]]("defined-sbt-plugins", "The set of names of Plugin implementations 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 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 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) diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index f9baefd0e..5bd13fd6a 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -140,7 +140,8 @@ object BuiltinCommands { def ConsoleCommands: Seq[Command] = Seq(ignore, exit, IvyConsole.command, setLogLevel, early, act, nop) def ScriptCommands: Seq[Command] = Seq(ignore, exit, Script.command, setLogLevel, early, act, nop) def DefaultCommands: Seq[Command] = Seq(ignore, help, completionsCommand, about, tasks, settingsCommand, loadProject, templateCommand, - projects, project, reboot, read, history, set, sessionCommand, inspect, loadProjectImpl, loadFailed, Cross.crossBuild, Cross.switchVersion, + projects, project, reboot, read, history, set, sessionCommand, inspect, loadProjectImpl, loadFailed, + Cross.crossBuild, Cross.switchVersion, PluginCross.pluginCross, PluginCross.pluginSwitch, setOnFailure, clearOnFailure, stashOnFailure, popOnFailure, setLogLevel, plugin, plugins, ifLast, multi, shell, continuous, eval, alias, append, last, lastGrep, export, boot, nop, call, exit, early, initialize, act) ++ compatCommands diff --git a/main/src/main/scala/sbt/PluginCross.scala b/main/src/main/scala/sbt/PluginCross.scala new file mode 100644 index 000000000..8bb08b0e0 --- /dev/null +++ b/main/src/main/scala/sbt/PluginCross.scala @@ -0,0 +1,72 @@ +/* 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 complete.DefaultParsers._ +import complete.Parser +import sbt.Keys._ +import Project._ +import Scope.GlobalScope +import Def.ScopedKey +import 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): Seq[String] = { + val x = Project.extract(state) + import x._ + crossSbtVersions in currentRef get structure.data getOrElse Nil + } + 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 + } + } +} diff --git a/notes/0.13.16/sbt-cross-building.markdown b/notes/0.13.16/sbt-cross-building.markdown new file mode 100644 index 000000000..e389a17bc --- /dev/null +++ b/notes/0.13.16/sbt-cross-building.markdown @@ -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 diff --git a/sbt/src/sbt-test/dependency-management/force-update-period/build.sbt b/sbt/src/sbt-test/dependency-management/force-update-period/build.sbt index b7505be1d..07c895626 100644 --- a/sbt/src/sbt-test/dependency-management/force-update-period/build.sbt +++ b/sbt/src/sbt-test/dependency-management/force-update-period/build.sbt @@ -2,6 +2,8 @@ libraryDependencies += "log4j" % "log4j" % "1.2.16" % "compile" autoScalaLibrary := false +crossPaths := false + TaskKey[Unit]("check-last-update-time") := (streams map { (s) => val fullUpdateOutput = s.cacheDirectory / "out" val timeDiff = System.currentTimeMillis()-fullUpdateOutput.lastModified() diff --git a/sbt/src/sbt-test/project/cross-plugins-defaults/build.sbt b/sbt/src/sbt-test/project/cross-plugins-defaults/build.sbt new file mode 100644 index 000000000..5327d2d20 --- /dev/null +++ b/sbt/src/sbt-test/project/cross-plugins-defaults/build.sbt @@ -0,0 +1,24 @@ +val baseSbt = "0.13" + +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.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") + }, + + 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.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") + } + ) diff --git a/sbt/src/sbt-test/project/cross-plugins-defaults/test b/sbt/src/sbt-test/project/cross-plugins-defaults/test new file mode 100644 index 000000000..a1d9be762 --- /dev/null +++ b/sbt/src/sbt-test/project/cross-plugins-defaults/test @@ -0,0 +1,5 @@ +> check + +> ^^ 1.0.0-M5 + +> check2 diff --git a/sbt/src/sbt-test/project/cross-plugins-source/build.sbt b/sbt/src/sbt-test/project/cross-plugins-source/build.sbt new file mode 100644 index 000000000..0da92976f --- /dev/null +++ b/sbt/src/sbt-test/project/cross-plugins-source/build.sbt @@ -0,0 +1,6 @@ +lazy val root = (project in file(".")) + .settings( + sbtPlugin := true, + sbtVersion in pluginCrossBuild := "0.12.4", + resolvers += Resolver.typesafeIvyRepo("releases") + ) diff --git a/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala-sbt-0.12.x/B.scala b/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala-sbt-0.12.x/B.scala new file mode 100644 index 000000000..0ed0a40b8 --- /dev/null +++ b/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala-sbt-0.12.x/B.scala @@ -0,0 +1,2 @@ +// folder mustn't be included +trait B diff --git a/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala-sbt-0.12/A.scala b/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala-sbt-0.12/A.scala new file mode 100644 index 000000000..16c5ea484 --- /dev/null +++ b/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala-sbt-0.12/A.scala @@ -0,0 +1 @@ +trait A \ No newline at end of file diff --git a/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala-sbt-0.12/B.scala b/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala-sbt-0.12/B.scala new file mode 100644 index 000000000..1e59c35e7 --- /dev/null +++ b/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala-sbt-0.12/B.scala @@ -0,0 +1 @@ +trait B diff --git a/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala/Test.scala b/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala/Test.scala new file mode 100644 index 000000000..3dc251c35 --- /dev/null +++ b/sbt/src/sbt-test/project/cross-plugins-source/src/main/scala/Test.scala @@ -0,0 +1 @@ +object Test extends A with B \ No newline at end of file diff --git a/sbt/src/sbt-test/project/cross-plugins-source/src/test/scala/TestFile.scala b/sbt/src/sbt-test/project/cross-plugins-source/src/test/scala/TestFile.scala new file mode 100644 index 000000000..f99e035ad --- /dev/null +++ b/sbt/src/sbt-test/project/cross-plugins-source/src/test/scala/TestFile.scala @@ -0,0 +1,3 @@ +// should fail because the project is building for +// 0.12.4 where E is not included +object ErrorTest extends E diff --git a/sbt/src/sbt-test/project/cross-plugins-source/test b/sbt/src/sbt-test/project/cross-plugins-source/test new file mode 100644 index 000000000..f3f14e7b2 --- /dev/null +++ b/sbt/src/sbt-test/project/cross-plugins-source/test @@ -0,0 +1,3 @@ +> show pluginCrossBuild::sbtDependency +> compile +-> test:compile diff --git a/sbt/src/sbt-test/project/scripted1/build.sbt b/sbt/src/sbt-test/project/scripted1/build.sbt new file mode 100644 index 000000000..331b2e7bb --- /dev/null +++ b/sbt/src/sbt-test/project/scripted1/build.sbt @@ -0,0 +1,6 @@ +lazy val root = (project in file(".")) + .settings( + scriptedSettings, + sbtPlugin := true, + resolvers += Resolver.typesafeIvyRepo("releases") + ) diff --git a/sbt/src/sbt-test/project/scripted13/changes/A.scala b/sbt/src/sbt-test/project/scripted1/changes/A.scala similarity index 100% rename from sbt/src/sbt-test/project/scripted13/changes/A.scala rename to sbt/src/sbt-test/project/scripted1/changes/A.scala diff --git a/sbt/src/sbt-test/project/scripted13/changes/Fail.scala b/sbt/src/sbt-test/project/scripted1/changes/Fail.scala similarity index 100% rename from sbt/src/sbt-test/project/scripted13/changes/Fail.scala rename to sbt/src/sbt-test/project/scripted1/changes/Fail.scala diff --git a/sbt/src/sbt-test/project/scripted13/disabled b/sbt/src/sbt-test/project/scripted1/disabled similarity index 71% rename from sbt/src/sbt-test/project/scripted13/disabled rename to sbt/src/sbt-test/project/scripted1/disabled index 3d9d074ff..ff5ce9c1a 100644 --- a/sbt/src/sbt-test/project/scripted13/disabled +++ b/sbt/src/sbt-test/project/scripted1/disabled @@ -1,5 +1,7 @@ # This tests that this sbt scripted plugin can launch the next one -# It is currently disabled because there is no next plugin version +# It is currently disabled because it requires JDK8 to run sbt 1.0. + +> ^^1.0.0-M5 $ copy-file changes/A.scala src/sbt-test/a/b/A.scala > scripted diff --git a/sbt/src/sbt-test/project/scripted1/project/plugins.sbt b/sbt/src/sbt-test/project/scripted1/project/plugins.sbt new file mode 100644 index 000000000..5f7aaa347 --- /dev/null +++ b/sbt/src/sbt-test/project/scripted1/project/plugins.sbt @@ -0,0 +1,5 @@ +libraryDependencies += { + "org.scala-sbt" % "scripted-plugin" % sbtVersion.value +} + +offline := true diff --git a/sbt/src/sbt-test/project/scripted13/src/sbt-test/a/b/test b/sbt/src/sbt-test/project/scripted1/src/sbt-test/a/b/test similarity index 100% rename from sbt/src/sbt-test/project/scripted13/src/sbt-test/a/b/test rename to sbt/src/sbt-test/project/scripted1/src/sbt-test/a/b/test diff --git a/sbt/src/sbt-test/project/scripted13/build.sbt b/sbt/src/sbt-test/project/scripted13/build.sbt deleted file mode 100644 index 45efde4f0..000000000 --- a/sbt/src/sbt-test/project/scripted13/build.sbt +++ /dev/null @@ -1,11 +0,0 @@ -scriptedSettings - -scriptedSbt := sbtVersion.value - -sbtPlugin := true - -sbtVersion in Global := "0.13.0-Beta2" - -scalaVersion in Global := "2.10.2-RC2" - -offline := true diff --git a/sbt/src/sbt-test/project/scripted13/project/plugins.sbt b/sbt/src/sbt-test/project/scripted13/project/plugins.sbt deleted file mode 100644 index a2a45d929..000000000 --- a/sbt/src/sbt-test/project/scripted13/project/plugins.sbt +++ /dev/null @@ -1,5 +0,0 @@ -libraryDependencies += { - "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value -} - -offline := true diff --git a/scripted/plugin/src/main/scala/sbt/ScriptedPlugin.scala b/scripted/plugin/src/main/scala/sbt/ScriptedPlugin.scala index b441c76ac..42a69e26b 100644 --- a/scripted/plugin/src/main/scala/sbt/ScriptedPlugin.scala +++ b/scripted/plugin/src/main/scala/sbt/ScriptedPlugin.scala @@ -9,6 +9,7 @@ import complete.{ Parser, DefaultParsers } import classpath.ClasspathUtilities import java.lang.reflect.{ InvocationTargetException, Method } import java.util.Properties +import CrossVersion.binarySbtVersion object ScriptedPlugin extends Plugin { def scriptedConf = config("scripted-sbt") hide @@ -97,13 +98,23 @@ object ScriptedPlugin extends Plugin { val scriptedSettings = Seq( ivyConfigurations ++= Seq(scriptedConf, scriptedLaunchConf), - scriptedSbt := sbtVersion.value, + scriptedSbt := (sbtVersion in pluginCrossBuild).value, sbtLauncher <<= getJars(scriptedLaunchConf).map(_.get.head), sbtTestDirectory := sourceDirectory.value / "sbt-test", - libraryDependencies ++= Seq( - "org.scala-sbt" % "scripted-sbt" % scriptedSbt.value % scriptedConf.toString, - "org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString - ), + libraryDependencies ++= { + binarySbtVersion(scriptedSbt.value) match { + 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, scriptedClasspath := getJars(scriptedConf).value, scriptedTests <<= scriptedTestsTask,