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
{
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 remoteID = SettingKey[String]("remote-id")
lazy val publishLauncher = TaskKey[String]("publish-launcher")
lazy val fullRelease = TaskKey[Unit]("full-release")
lazy val prerelease = TaskKey[Unit]("prerelease")
lazy val launcherRemotePath = SettingKey[String]("launcher-remote-path")
lazy val deployLauncher = TaskKey[Unit]("deploy-launcher", "Upload the launcher to its traditional location for compatibility with existing scripts.")
lazy val pushWiki = TaskKey[Unit]("push-wiki")
lazy val pushMain = TaskKey[Unit]("push-main")
val PublishRepoHost = "typesafe.artifactoryonline.com"
def settings(nonRoots: => Seq[ProjectReference], launcher: ScopedTask[File]): Seq[Setting[_]] =
if(CredentialsFile.exists)
releaseSettings(nonRoots, launcher) /* ++ fullReleaseSettings */
else
Nil
if(CredentialsFile.exists) releaseSettings(nonRoots, launcher) else Nil
def releaseSettings(nonRoots: => Seq[ProjectReference], launcher: ScopedTask[File]): Seq[Setting[_]] = Seq(
publishTo in ThisBuild <<= publishResolver,
remoteID <<= publishStatus("typesafe-ivy-" + _),
credentials in ThisBuild += Credentials(CredentialsFile),
remoteBase <<= publishStatus( "https://" + PublishRepoHost + "/typesafe/ivy-" + _ ),
publishAllArtifacts <<= Util.inAll(nonRoots, publish.task),
publishLauncher <<= deployLauncher(launcher),
publishRelease <<= Seq(publishLauncher, publishAllArtifacts).dependOn,
launcherRemotePath <<= (organization, version) { (org, v) => List(org, LaunchJarName, v, LaunchJarName + ".jar").mkString("/") }
)
def fullReleaseSettings: Seq[Setting[_]] = Seq(
pushMain <<= pushMain0,
prerelease := println(Prerelease),
fullRelease <<= fullRelease0
launcherRemotePath <<= (organization, version, moduleName) { (org, v, n) => List(org, n, v, n + ".jar").mkString("/") },
publish <<= Seq(publish, Release.deployLauncher).dependOn,
deployLauncher <<= deployLauncher(launcher)
)
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]) =
(launcher, launcherRemotePath, credentials, remoteBase, streams) map { (launchJar, remotePath, creds, base, s) =>
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
try { http(request.as_str) } finally { http.shutdown() }
()
}
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)
}
}
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;
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))
/* ** Subproject declarations ** */
@ -186,6 +186,7 @@ object Sbt extends Build
lazy val scripted = InputKey[Unit]("scripted")
lazy val scriptedSource = SettingKey[File]("scripted-source")
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 deep[T](scoped: ScopedSetting[T]): Initialize[Seq[T]] =
@ -194,7 +195,6 @@ object Sbt extends Build
def launchSettings =
Seq(ivy, crossPaths := false,
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.transSourceSettings ++ Seq(
@ -205,7 +205,7 @@ object Sbt extends Build
import Sxr.sxr
def releaseSettings = Release.settings(nonRoots, proguard in Proguard)
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(
scripted <<= scriptedTask,
scriptedSource <<= (sourceDirectory in sbtSub) / "sbt-test",
@ -219,7 +219,18 @@ object Sbt extends Build
ci.copy(config = ci.config.copy(options = opts))
},
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))))

View File

@ -55,7 +55,7 @@ object ScriptedPlugin extends Plugin {
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 from launcherURL(scriptedSbt.value)
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString
),
scriptedBufferLog := true,
scriptedClasspath := getJars(scriptedConf).value,
@ -68,6 +68,4 @@ object ScriptedPlugin extends Plugin {
private[this] def getJars(config: Configuration): Initialize[Task[PathFinder]] = Def.task {
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"
}