Build cleanup, publish launcher normally, pull it normally in scripted plugin

Still want to deploy the launcher to the previous path for compatibility with
existing scripts so that the transition to 0.13 is not impeded.
This commit is contained in:
Mark Harrah 2013-06-20 14:28:05 -04:00
parent f5febfae0e
commit 280e1b6d60
3 changed files with 35 additions and 82 deletions

View File

@ -5,47 +5,44 @@
object Release extends Build object Release extends Build
{ {
lazy val publishRelease = TaskKey[Unit]("publish-release")
lazy val publishAllArtifacts = TaskKey[Unit]("publish-all-artifacts")
lazy val launcherRemotePath = SettingKey[String]("launcher-remote-path")
lazy val remoteBase = SettingKey[String]("remote-base") lazy val remoteBase = SettingKey[String]("remote-base")
lazy val remoteID = SettingKey[String]("remote-id") lazy val remoteID = SettingKey[String]("remote-id")
lazy val publishLauncher = TaskKey[String]("publish-launcher") lazy val launcherRemotePath = SettingKey[String]("launcher-remote-path")
lazy val fullRelease = TaskKey[Unit]("full-release") lazy val deployLauncher = TaskKey[Unit]("deploy-launcher", "Upload the launcher to its traditional location for compatibility with existing scripts.")
lazy val prerelease = TaskKey[Unit]("prerelease")
lazy val pushWiki = TaskKey[Unit]("push-wiki")
lazy val pushMain = TaskKey[Unit]("push-main")
val PublishRepoHost = "typesafe.artifactoryonline.com" val PublishRepoHost = "typesafe.artifactoryonline.com"
def settings(nonRoots: => Seq[ProjectReference], launcher: ScopedTask[File]): Seq[Setting[_]] = def settings(nonRoots: => Seq[ProjectReference], launcher: ScopedTask[File]): Seq[Setting[_]] =
if(CredentialsFile.exists) if(CredentialsFile.exists) releaseSettings(nonRoots, launcher) else Nil
releaseSettings(nonRoots, launcher) /* ++ fullReleaseSettings */
else
Nil
def releaseSettings(nonRoots: => Seq[ProjectReference], launcher: ScopedTask[File]): Seq[Setting[_]] = Seq( def releaseSettings(nonRoots: => Seq[ProjectReference], launcher: ScopedTask[File]): Seq[Setting[_]] = Seq(
publishTo in ThisBuild <<= publishResolver, publishTo in ThisBuild <<= publishResolver,
remoteID <<= publishStatus("typesafe-ivy-" + _), remoteID <<= publishStatus("typesafe-ivy-" + _),
credentials in ThisBuild += Credentials(CredentialsFile), credentials in ThisBuild += Credentials(CredentialsFile),
remoteBase <<= publishStatus( "https://" + PublishRepoHost + "/typesafe/ivy-" + _ ), remoteBase <<= publishStatus( "https://" + PublishRepoHost + "/typesafe/ivy-" + _ ),
publishAllArtifacts <<= Util.inAll(nonRoots, publish.task), launcherRemotePath <<= (organization, version, moduleName) { (org, v, n) => List(org, n, v, n + ".jar").mkString("/") },
publishLauncher <<= deployLauncher(launcher), publish <<= Seq(publish, Release.deployLauncher).dependOn,
publishRelease <<= Seq(publishLauncher, publishAllArtifacts).dependOn, deployLauncher <<= deployLauncher(launcher)
launcherRemotePath <<= (organization, version) { (org, v) => List(org, LaunchJarName, v, LaunchJarName + ".jar").mkString("/") }
)
def fullReleaseSettings: Seq[Setting[_]] = Seq(
pushMain <<= pushMain0,
prerelease := println(Prerelease),
fullRelease <<= fullRelease0
) )
def snapshotPattern(version: String) = Resolver.localBasePattern.replaceAll("""\[revision\]""", version)
def publishResolver: Project.Initialize[Option[Resolver]] = (remoteID, remoteBase) { (id, base) =>
Some( Resolver.url("publish-" + id, url(base))(Resolver.ivyStylePatterns) )
}
lazy val CredentialsFile: File = Path.userHome / ".ivy2" / ".typesafe-credentials"
// this is no longer strictly necessary, since the launcher is now published as normal
// however, existing scripts expect the launcher to be in a certain place and normal publishing adds "jars/"
// to the published path
def deployLauncher(launcher: ScopedTask[File]) = def deployLauncher(launcher: ScopedTask[File]) =
(launcher, launcherRemotePath, credentials, remoteBase, streams) map { (launchJar, remotePath, creds, base, s) => (launcher, launcherRemotePath, credentials, remoteBase, streams) map { (launchJar, remotePath, creds, base, s) =>
val (uname, pwd) = getCredentials(creds, s.log) val (uname, pwd) = getCredentials(creds, s.log)
val request = dispatch.classic.url(base) / remotePath <<< (launchJar, BinaryType) as (uname, pwd) val request = dispatch.classic.url(base) / remotePath <<< (launchJar, "binary/octet-stream") as (uname, pwd)
val http = new dispatch.classic.Http val http = new dispatch.classic.Http
try { http(request.as_str) } finally { http.shutdown() } try { http(request.as_str) } finally { http.shutdown() }
()
} }
def getCredentials(cs: Seq[Credentials], log: Logger): (String, String) = def getCredentials(cs: Seq[Credentials], log: Logger): (String, String) =
{ {
@ -54,57 +51,4 @@ object Release extends Build
case None => error("No credentials defined for " + PublishRepoHost) case None => error("No credentials defined for " + PublishRepoHost)
} }
} }
def snapshotPattern(version: String) = Resolver.localBasePattern.replaceAll("""\[revision\]""", version)
def publishResolver: Project.Initialize[Option[Resolver]] = (remoteID, remoteBase) { (id, base) =>
Some( Resolver.url("publish-" + id, url(base))(Resolver.ivyStylePatterns) )
}
def updatedRepo(repo: SettingKey[File], remote: SettingKey[String], branch: Option[String]) =
(repo, remote, streams) map { (local, uri, s) => updated(remote = uri, cwd = local, branch = branch, log = s.log); local }
def fullRelease0 = Seq(pushMain, publishRelease).dependOn
def pushMain0 = (baseDirectory, version, streams) map { (repo, v, s) => commitAndPush(v, tag = Some("v" + v))(repo, s.log) }
def commitAndPush(msg: String, tag: Option[String] = None)(repo: File, log: Logger)
{
git("add", ".")(repo, log)
git("commit", "-m", msg, "--allow-empty")(repo, log)
for(tagString <- tag) git("tag", tagString)(repo, log)
push(repo, log)
}
def push(cwd: File, log: Logger) = git("push", "--tags", "-n")(cwd, log)
def pull(cwd: File, log: Logger) = git("pull")(cwd, log)
def updated(remote: String, branch: Option[String], cwd: File, log: Logger): Unit =
if(cwd.exists)
pull(cwd, log)
else
branch match {
case None => git("clone", remote, ".")(cwd, log)
case Some(b) => git("clone", "-b", b, remote, ".")(cwd, log)
}
def git(args: String*)(cwd: File, log: Logger): Unit =
{
IO.createDirectory(cwd)
val full = "git" +: args
log.info(cwd + "$ " + full.mkString(" "))
val code = Process(full, cwd) ! log
if(code != 0) error("Nonzero exit code for git " + args.take(1).mkString + ": " + code)
}
final val BinaryType = "binary/octet-stream"
final val RemoteHost = "typesafe.artifactoryonline.com"
final val RemoteRealm = "Artifactory Realm"
final val LaunchJarName = "sbt-launch"
lazy val CredentialsFile: File = Path.userHome / ".ivy2" / ".typesafe-credentials"
def Prerelease = """
Before running full-release, the following should be done manually from the root 'xsbt' project:
1. Ensure all code is committed and the working directory is completely clean. 'git status' should show no untracked files.
2. 'test'
3. 'scripted'
4. Set the release version in README, build definition, and in src/main/conscript configurations.
5. Run 'show updated-wiki-repository'. Update versions, documentation for release in displayed directory.
6. Add notes/<version>.markdown
7. 'preview-notes'
"""
} }

View File

@ -28,7 +28,7 @@ object Sbt extends Build
lazy val myProvided = config("provided") intransitive; lazy val myProvided = config("provided") intransitive;
override def projects = super.projects.map(p => p.copy(configurations = (p.configurations.filter(_ != Provided)) :+ myProvided)) override def projects = super.projects.map(p => p.copy(configurations = (p.configurations.filter(_ != Provided)) :+ myProvided))
lazy val root: Project = Project("xsbt", file("."), aggregate = nonRoots ) settings( rootSettings : _*) configs( Sxr.sxrConf, Proguard ) lazy val root: Project = Project("root", file("."), aggregate = nonRoots ) settings( rootSettings : _*) configs( Sxr.sxrConf, Proguard )
lazy val nonRoots = projects.filter(_ != root).map(p => LocalProject(p.id)) lazy val nonRoots = projects.filter(_ != root).map(p => LocalProject(p.id))
/* ** Subproject declarations ** */ /* ** Subproject declarations ** */
@ -186,6 +186,7 @@ object Sbt extends Build
lazy val scripted = InputKey[Unit]("scripted") lazy val scripted = InputKey[Unit]("scripted")
lazy val scriptedSource = SettingKey[File]("scripted-source") lazy val scriptedSource = SettingKey[File]("scripted-source")
lazy val publishAll = TaskKey[Unit]("publish-all") lazy val publishAll = TaskKey[Unit]("publish-all")
lazy val publishLauncher = TaskKey[Unit]("publish-launcher")
def deepTasks[T](scoped: ScopedTask[Seq[T]]): Initialize[Task[Seq[T]]] = deep(scoped.task) { _.join.map(_.flatten.distinct) } def deepTasks[T](scoped: ScopedTask[Seq[T]]): Initialize[Task[Seq[T]]] = deep(scoped.task) { _.join.map(_.flatten.distinct) }
def deep[T](scoped: ScopedSetting[T]): Initialize[Seq[T]] = def deep[T](scoped: ScopedSetting[T]): Initialize[Seq[T]] =
@ -194,7 +195,6 @@ object Sbt extends Build
def launchSettings = def launchSettings =
Seq(ivy, crossPaths := false, Seq(ivy, crossPaths := false,
compile in Test <<= compile in Test dependsOn(publishLocal in interfaceSub, publishLocal in testSamples, publishLocal in launchInterfaceSub) compile in Test <<= compile in Test dependsOn(publishLocal in interfaceSub, publishLocal in testSamples, publishLocal in launchInterfaceSub)
// mappings in (Compile, packageBin) <++= (mappings in (launchInterfaceSub, Compile, packageBin) ).identity
) ++ ) ++
inConfig(Compile)(Transform.configSettings) ++ inConfig(Compile)(Transform.configSettings) ++
inConfig(Compile)(Transform.transSourceSettings ++ Seq( inConfig(Compile)(Transform.transSourceSettings ++ Seq(
@ -205,7 +205,7 @@ object Sbt extends Build
import Sxr.sxr import Sxr.sxr
def releaseSettings = Release.settings(nonRoots, proguard in Proguard) def releaseSettings = Release.settings(nonRoots, proguard in Proguard)
def rootSettings = releaseSettings ++ Docs.settings ++ LaunchProguard.settings ++ LaunchProguard.specific(launchSub) ++ def rootSettings = releaseSettings ++ Docs.settings ++ LaunchProguard.settings ++ LaunchProguard.specific(launchSub) ++
Sxr.settings ++ docSetting ++ Util.publishPomSettings ++ otherRootSettings Sxr.settings ++ docSetting ++ Util.publishPomSettings ++ otherRootSettings ++ proguardedLauncherSettings
def otherRootSettings = Seq( def otherRootSettings = Seq(
scripted <<= scriptedTask, scripted <<= scriptedTask,
scriptedSource <<= (sourceDirectory in sbtSub) / "sbt-test", scriptedSource <<= (sourceDirectory in sbtSub) / "sbt-test",
@ -219,7 +219,18 @@ object Sbt extends Build
ci.copy(config = ci.config.copy(options = opts)) ci.copy(config = ci.config.copy(options = opts))
}, },
publishAll <<= inAll(nonRoots, publishLocal.task), publishAll <<= inAll(nonRoots, publishLocal.task),
TaskKey[Unit]("build-all") <<= (publishAll, proguard in Proguard, sxr, doc) map { (_,_,_,_) => () } publishAll <<= (publishAll, publishLocal).map((x,y)=> ()), // publish all normal deps as well as the sbt-launch jar
TaskKey[Unit]("build-all") <<= Seq(publishLocal, /*sxr,*/ doc).dependOn
)
// the launcher is published with metadata so that the scripted plugin can pull it in
// being proguarded, it shouldn't ever be on a classpath with other jars, however
def proguardedLauncherSettings = Seq(
publishArtifact in packageSrc := false,
moduleName := "sbt-launch",
autoScalaLibrary := false,
description := "sbt application launcher",
publishLauncher <<= publish,
packageBin in Compile <<= (proguard in Proguard).identity
) )
def docSetting = inConfig(Compile)(inTask(sxr)(Defaults.docSetting(doc in ThisScope.copy(task = Global, config = Global)))) def docSetting = inConfig(Compile)(inTask(sxr)(Defaults.docSetting(doc in ThisScope.copy(task = Global, config = Global))))

View File

@ -55,7 +55,7 @@ object ScriptedPlugin extends Plugin {
sbtTestDirectory := sourceDirectory.value / "sbt-test", sbtTestDirectory := sourceDirectory.value / "sbt-test",
libraryDependencies ++= Seq( libraryDependencies ++= Seq(
"org.scala-sbt" % "scripted-sbt" % scriptedSbt.value % scriptedConf.toString, "org.scala-sbt" % "scripted-sbt" % scriptedSbt.value % scriptedConf.toString,
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString from launcherURL(scriptedSbt.value) "org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString
), ),
scriptedBufferLog := true, scriptedBufferLog := true,
scriptedClasspath := getJars(scriptedConf).value, scriptedClasspath := getJars(scriptedConf).value,
@ -68,6 +68,4 @@ object ScriptedPlugin extends Plugin {
private[this] def getJars(config: Configuration): Initialize[Task[PathFinder]] = Def.task { private[this] def getJars(config: Configuration): Initialize[Task[PathFinder]] = Def.task {
PathFinder(Classpaths.managedJars(config, classpathTypes.value, update.value).map(_.data)) PathFinder(Classpaths.managedJars(config, classpathTypes.value, update.value).map(_.data))
} }
private[this] def launcherURL(v: String): String =
"http://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/" + v + "/sbt-launch.jar"
} }