Merge pull request #4 from jsuereth/master

Step #1: Make the template project a plugin that other can use
This commit is contained in:
Paul Phillips 2011-09-14 10:34:01 -07:00
commit 7e759c1862
4 changed files with 148 additions and 122 deletions

View File

@ -7,6 +7,7 @@ project directory, the runner will figure out the versions of sbt
and scala required by the project and download them if necessary. and scala required by the project and download them if necessary.
There's also a template project sbt coming together, but it's unfinished. There's also a template project sbt coming together, but it's unfinished.
See below for how to pull the template project in as a plugin.
However the runner is quite useful already. However the runner is quite useful already.
Here's a sample use of the runner: it creates a new project using a Here's a sample use of the runner: it creates a new project using a
@ -97,3 +98,25 @@ Current -help output:
In the case of duplicated or conflicting options, the order above In the case of duplicated or conflicting options, the order above
shows precedence: JAVA_OPTS lowest, command line options highest. shows precedence: JAVA_OPTS lowest, command line options highest.
## Template project
To gain access to the awesome, simply add the following <project>/project/plugins/project/Build.scala file:
import sbt._
object PluginDef extends Build {
override def projects = Seq(root)
lazy val root = Project("plugins", file(".")) dependsOn(extras)
lazy val extras = uri("git://github.com/jsuereth/sbt-extras")
}
Now to continue the amazement, simply extend the TemplateBuild trait in your project. For example, in your
<project>/project/Build.scala file add:
import sbt._
import template.TemplateBuild
object MyAwesomeBuild extends TemplateBuild {}
The Template build isn't quite finished. There will most likely be a build.sbt DSL variant that does not require a project scala file.

8
build.sbt Normal file
View File

@ -0,0 +1,8 @@
sbtPlugin := true
name := "sbt-extras-plugin"
organization := "org.improving"
version <<= (sbtVersion)("0.1.0-%s".format(_))

View File

@ -1,119 +0,0 @@
import sbt._
import Keys._
import Load.{ BuildStructure, StructureIndex }
import scala.collection.{ mutable, immutable }
trait SbtCreateConfig {
def name: String
def organization: String
def version: String
def scalaVersion: String
}
object SbtCreateConfig {
private def prop(propName: String, alt: String) = System.getProperty(propName) match {
case null => alt
case value => value
}
implicit def defaultProjectConfig = new SbtCreateConfig {
def name = prop("sbt-create.name", "project-name-here")
def organization = prop("sbt-create.organization", "your.organization.here")
def version = prop("sbt-create.version", "0.1-SNAPSHOT")
def scalaVersion = prop("sbt.scala.version", "2.9.0-1")
}
}
class TemplateBuild(implicit sbtCreateConfig: SbtCreateConfig) extends Build {
// BuildStructure contains:
// units: Map[URI, LoadedBuildUnit]
// root: URI
// settings: Seq[Setting[_]]
// data: Settings[Scope]
// index: StructureIndex
// streams: Streams
// delegates: Scope => Seq[Scope]
// scopeLocal: ScopeLocal
private val cachedExtraction = new collection.mutable.HashMap[State, WState]
private implicit def stateWrapper(state: State): WState =
cachedExtraction.getOrElseUpdate(state, new WState(state))
private implicit def revealStructure(state: State): BuildStructure =
stateWrapper(state).structure
private implicit def revealStructureIndex(state: State): StructureIndex =
revealStructure(state).index
private implicit def revealSession(state: State): SessionSettings =
stateWrapper(state).session
private class WState(state: State) {
val extracted = Project extract state
def projectId = extracted.currentProject.id
def structure = extracted.structure
def session = extracted.session
def currentRef = extracted.currentRef
def rootProject = structure.rootProject
def allProjects = structure.allProjects
def index = structure.index
def taskToKey = index.taskToKey
def keyMap = index.keyMap // Map[String, AttributeKey[_]]
def keyIndex = index.keyIndex
def currentKeys = keyIndex keys Some(currentRef) map index.keyMap
def sortedKeys = currentKeys.toSeq sortBy (_.label)
}
private class Tap[T](target: T) {
def show(): Unit = target match {
case xs: TraversableOnce[_] => xs foreach println
case _ => println(target)
}
def tap[U](f: T => U): T = {
f(target)
target
}
}
private implicit def createTapper[T](target: T): Tap[T] = new Tap(target)
def currentBranch = ("git status -sb".lines_! headOption) getOrElse "-" stripPrefix "## "
val buildShellPrompt = {
(state: State) => "%s:%s>".format(
state.projectId,
currentBranch
)
}
lazy val testSettings = Seq(
libraryDependencies ++= Seq(
"org.scala-tools.testing" % "specs_2.9.0-1" % "1.6.8" % "test"
),
libraryDependencies <+= (scalaVersion)(v => "org.scala-lang" % "scala-compiler" % v)
)
lazy val buildSettings = Seq(
resolvers += ScalaToolsSnapshots,
organization := sbtCreateConfig.organization,
version := sbtCreateConfig.version,
scalaVersion := sbtCreateConfig.scalaVersion,
// retrieveManaged := true,
shellPrompt := buildShellPrompt
// logLevel := Level.Debug,
)
lazy val templateConfig = Project(
id = sbtCreateConfig.name,
base = file("."),
aggregate = Nil,
dependencies = Nil,
delegates = Nil,
settings = Defaults.defaultSettings ++ buildSettings ++ testSettings ++ Seq(
commands += helpNames
)
)
// A sample command definition.
def helpNames = Command.command("help-names") { (state: State) =>
state tap (_.sortedKeys map (_.label) show)
}
}
object TemplateBuild extends TemplateBuild { }

View File

@ -1,7 +1,121 @@
package template package template
object Main { import sbt._
def main(args: Array[String]): Unit = { import Keys._
println("Skeleton main, reporting for duty on " + util.Properties.versionString) import Load.{ BuildStructure, StructureIndex }
import scala.collection.{ mutable, immutable }
object SbtExtrasPlugin extends Plugin {}
trait SbtCreateConfig {
def name: String
def organization: String
def version: String
def scalaVersion: String
}
object SbtCreateConfig {
private def prop(propName: String, alt: String) = System.getProperty(propName) match {
case null => alt
case value => value
}
implicit def defaultProjectConfig = new SbtCreateConfig {
def name = prop("sbt-create.name", "project-name-here")
def organization = prop("sbt-create.organization", "your.organization.here")
def version = prop("sbt-create.version", "0.1-SNAPSHOT")
def scalaVersion = prop("sbt.scala.version", "2.9.0-1")
}
}
class TemplateBuild(implicit sbtCreateConfig: SbtCreateConfig) extends Build {
// BuildStructure contains:
// units: Map[URI, LoadedBuildUnit]
// root: URI
// settings: Seq[Setting[_]]
// data: Settings[Scope]
// index: StructureIndex
// streams: Streams
// delegates: Scope => Seq[Scope]
// scopeLocal: ScopeLocal
private val cachedExtraction = new collection.mutable.HashMap[State, WState]
private implicit def stateWrapper(state: State): WState =
cachedExtraction.getOrElseUpdate(state, new WState(state))
private implicit def revealStructure(state: State): BuildStructure =
stateWrapper(state).structure
private implicit def revealStructureIndex(state: State): StructureIndex =
revealStructure(state).index
private implicit def revealSession(state: State): SessionSettings =
stateWrapper(state).session
private class WState(state: State) {
val extracted = Project extract state
def projectId = extracted.currentProject.id
def structure = extracted.structure
def session = extracted.session
def currentRef = extracted.currentRef
def rootProject = structure.rootProject
def allProjects = structure.allProjects
def index = structure.index
def taskToKey = index.taskToKey
def keyMap = index.keyMap // Map[String, AttributeKey[_]]
def keyIndex = index.keyIndex
def currentKeys = keyIndex keys Some(currentRef) map index.keyMap
def sortedKeys = currentKeys.toSeq sortBy (_.label)
}
private class Tap[T](target: T) {
def show(): Unit = target match {
case xs: TraversableOnce[_] => xs foreach println
case _ => println(target)
}
def tap[U](f: T => U): T = {
f(target)
target
}
}
private implicit def createTapper[T](target: T): Tap[T] = new Tap(target)
def currentBranch = ("git status -sb".lines_! headOption) getOrElse "-" stripPrefix "## "
val buildShellPrompt = {
(state: State) => "%s:%s> ".format(
state.projectId,
currentBranch
)
}
lazy val testSettings = Seq(
libraryDependencies ++= Seq(
"org.scala-tools.testing" % "specs_2.9.0-1" % "1.6.8" % "test"
),
libraryDependencies <+= (scalaVersion)(v => "org.scala-lang" % "scala-compiler" % v)
)
lazy val buildSettings = Seq(
resolvers += ScalaToolsSnapshots,
organization := sbtCreateConfig.organization,
version := sbtCreateConfig.version,
scalaVersion := sbtCreateConfig.scalaVersion,
// retrieveManaged := true,
shellPrompt := buildShellPrompt
// logLevel := Level.Debug,
)
lazy val templateConfig = Project(
id = sbtCreateConfig.name,
base = file("."),
aggregate = Nil,
dependencies = Nil,
delegates = Nil,
settings = Defaults.defaultSettings ++ buildSettings ++ testSettings ++ Seq(
commands += helpNames
)
)
// A sample command definition.
def helpNames = Command.command("help-names") { (state: State) =>
state tap (_.sortedKeys map (_.label) show)
} }
} }