Skip to content

Commit

Permalink
Merge pull request #8 from skyluc/wip/scala-osgi-support
Browse files Browse the repository at this point in the history
UpdateScalaIDEManifests working on Scala's osgi bundles
  • Loading branch information
skyluc committed Oct 15, 2013
2 parents 8673e48 + f648d9f commit 8a1985e
Show file tree
Hide file tree
Showing 17 changed files with 1,181 additions and 86 deletions.
9 changes: 5 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
name := "build-tools"

version := "0.3.9-SNAPSHOT"
version := "0.4.0-SNAPSHOT"

organization := "org.scala-ide"

scalaVersion := "2.9.2"
scalaVersion := "2.10.3"

publishMavenStyle := true

publishTo := Some("Typesafe IDE" at "https://typesafe.artifactoryonline.com/typesafe/ide-2.9")
publishTo := Some("Typesafe IDE" at "https://private-repo.typesafe.com/typesafe/ide-2.10")
//publishTo := Some(Resolver.file("file", new File(Path.userHome.absolutePath+"/.m2/repository")))

credentials += Credentials(Path.userHome / ".credentials")
Expand All @@ -19,4 +19,5 @@ libraryDependencies ++= Seq(
"com.typesafe" % "config" % "0.5.2",
"junit" % "junit" % "4.8.1" % "test",
"org.slf4j" % "slf4j-simple" % "1.6.4",
"com.novocode" % "junit-interface" % "0.10-M1" % "test")
"com.novocode" % "junit-interface" % "0.10-M1" % "test",
"commons-io" % "commons-io" % "2.4")
1 change: 1 addition & 0 deletions project/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=0.13.0
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.3.0")
2 changes: 2 additions & 0 deletions src/main/scala/org/scalaide/buildtools/Ecosystem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ object Ecosystem {
/* osgi ids of the relevant bundles */
val ScalaLibraryId = "org.scala-ide.scala.library"
val ScalaCompilerId = "org.scala-ide.scala.compiler"
val ScalaLangLibraryId = "org.scala-lang.scala-library"
val ScalaLangCompilerId = "org.scala-lang.scala-compiler"
val ScalaIDEId = "org.scala-ide.sdt.core"
val ScalaIDEFeatureId = "org.scala-ide.sdt.feature"
val ScalaIDESourceFeatureId = "org.scala-ide.sdt.source.feature"
Expand Down
76 changes: 39 additions & 37 deletions src/main/scala/org/scalaide/buildtools/UpdateAddonManifests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object UpdateAddonManifests {
// parse arguments

val (repoURL, rootFolder) = args.toList match {
case RootOption(_) :: Nil | Nil =>
case RootOption(_) :: Nil | Nil =>
Console.err.println(usage)
Console.err.println("ERROR: missing repository URL")
System.exit(1).asInstanceOf[Nothing]
Expand All @@ -26,18 +26,23 @@ object UpdateAddonManifests {
case url :: _ =>
(url, System.getProperty("user.dir"))
}

// does the job
val result = new UpdateAddonManifests(repoURL, rootFolder)()

// check the result
for {
error <- result.left
} {
Console.err.println("ERROR: %s".format(error))
System.exit(2)
}
try {
// does the job
val result = new UpdateAddonManifests(repoURL, rootFolder)()

// check the result
for {
error <- result.left
} {
Console.err.println("ERROR: %s".format(error))
System.exit(2)
}

} finally {
// need to stop Dispatch in any cases
Http.shutdown()
}
}

}
Expand All @@ -47,15 +52,13 @@ class UpdateAddonManifests(repoURL: String, rootFolder: String) {
import Ecosystem._

def apply(): Either[String, String] = {
val res= P2Repository.fromUrl(repoURL) match {
val res = P2Repository.fromUrl(repoURL) match {
case r: ValidP2Repository =>
updateVersions(r)
case ErrorP2Repository(msg, _) =>
Left(msg)
}

// need to stop Dispatch in any cases
Http.shutdown()

res
}

Expand All @@ -67,8 +70,8 @@ class UpdateAddonManifests(repoURL: String, rootFolder: String) {
for {
scalaIDEVersion <- getOneVersion(p2Repo, ScalaIDEId).right
// TODO: the version should be the one scalaIDE depends on
scalaLibraryVersion <- getOneVersion(p2Repo, ScalaLibraryId).right
scalaCompilerVersion <- getOneVersion(p2Repo, ScalaCompilerId).right
scalaLibraryVersion <- getOneVersion(p2Repo, ScalaLangLibraryId).right
scalaCompilerVersion <- getOneVersion(p2Repo, ScalaLangCompilerId).right
scalaIDEFeatureVersion <- getOneVersion(p2Repo, ScalaIDEFeatureIdOsgi).right
result <- updateVersions(scalaIDEVersion, scalaLibraryVersion, scalaCompilerVersion, scalaIDEFeatureVersion).right
} yield result
Expand All @@ -83,36 +86,35 @@ class UpdateAddonManifests(repoURL: String, rootFolder: String) {

val root = new File(rootFolder)


if (root.exists && root.isDirectory) {
// update the plugin manifest files
val versionUpdater: PartialFunction[String, String] = updateVersionInManifest(ScalaLibraryId, scalaLibraryVersion).
orElse(updateVersionInManifest(ScalaCompilerId, scalaCompilerVersion)).
orElse(updateVersionInManifest(ScalaIDEId, scalaIDEVersion)).
orElse {
val versionUpdater: PartialFunction[String, String] = updateVersionInManifest(ScalaLangLibraryId, scalaLibraryVersion).
orElse(updateVersionInManifest(ScalaLangCompilerId, scalaCompilerVersion)).
orElse(updateVersionInManifest(ScalaIDEId, scalaIDEVersion)).
orElse {
case line =>
line
}
line
}
findPlugins(root).foreach(updateVersionInPluginManifest(_, versionUpdater))

// update the feature definition files
findFeatures(root).foreach(updateVersionInFeature(_, scalaIDEFeatureVersion))

Right("OK")
} else {
Left("%s doesn't exist or is not a directory".format(root.getAbsolutePath()))
}
}

/**
* Set strict version dependency to the Scala IDE plugin in the given manifest file.
*/
private def updateVersionInPluginManifest(manifest: File, versionUpdater: PartialFunction[String, String]) {
println(manifest.getAbsoluteFile())

updateBundleManifest(manifest, versionUpdater)
}

/**
* Go through the feature definition XML tree, and add version and match attribute for the reference to the scala IDE feature.
*/
Expand All @@ -126,23 +128,23 @@ class UpdateAddonManifests(repoURL: String, rootFolder: String) {
}))
}
}

/**
* Set strict version dependency to Scala IDE feature in the given feature file.
*/
private def updateVersionInFeature(feature: File, scalaIDEFeatureVersion: Version): Either[String, String] = {
println(feature.getAbsoluteFile())
val savedFeature= new File(feature.getAbsolutePath() + OriginalSuffix)

val savedFeature = new File(feature.getAbsolutePath() + OriginalSuffix)

if (!savedFeature.exists) {
FileUtils.copyFile(feature, savedFeature)
}
val xml= transformXML(XML.loadFile(savedFeature), scalaIDEFeatureVersion)

val xml = transformXML(XML.loadFile(savedFeature), scalaIDEFeatureVersion)

XML.save(feature.getAbsolutePath(), xml, "UTF-8", true)

Right("OK")
}

Expand Down
115 changes: 71 additions & 44 deletions src/main/scala/org/scalaide/buildtools/UpdateScalaIDEManifests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,92 +5,119 @@ import scala.io.Source
import java.io.FileWriter
import org.osgi.framework.Version
import dispatch.Http
import java.util.zip.ZipFile

object UpdateScalaIDEManifests {

import Ecosystem._

final val Usage = "Usage: app [--root=<Scala IDE root folder>]"

final val PackagedManifestPath = "target/" + PluginManifest

final val BundleVersion = "Bundle-Version: (.*)".r

final val projectsToUpdate = List(ScalaIDEId, "org.scala-ide.sdt.debug")

def main(args: Array[String]) {
// parse arguments

val rootFolder = args.collectFirst {
case RootOption(root) =>
root
}.getOrElse(System.getProperty("user.dir"))
val (scalaVersion, m2Repo, scalaIDERootOpt) = parseArgs(args.toList)

val scalaIDERoot = scalaIDERootOpt match {
case Some(folder) =>
new File(folder)
case None =>
new File(System.getProperty("user.dir"))
}

new UpdateScalaIDEManifests(scalaVersion, new File(m2Repo), scalaIDERoot)()

new UpdateScalaIDEManifests(rootFolder)()

}

private def parseArgs(args: List[String]): (String, String, Option[String]) = {

def usageError(message: String): Nothing = {
Console.err.println(s"Error: $message. Was : ${args.mkString(" ")}")
Console.err.println("usage: app [--root=<Scala IDE root folder>] <scala version> <m2 repository folder>")
sys.exit(1)
}

def parseArgsVersion(args: List[String], scalaIDERootOpt: Option[String]): (String, String, Option[String]) = {
args match {
case RootOption(root) :: tail =>
parseArgsVersion(tail, Some(root))
case version :: tail =>
parseArgsM2Repo(tail, version, scalaIDERootOpt)
case _ =>
usageError("Missing arguments")
}
}

def parseArgsM2Repo(args: List[String], scalaVersion: String, scalaIDERootOpt: Option[String]): (String, String, Option[String]) = {
args match {
case RootOption(root) :: tail =>
parseArgsM2Repo(tail, scalaVersion, Some(root))
case m2Repo :: tail =>
parseArgsRemainder(tail, scalaVersion, m2Repo, scalaIDERootOpt)
case _ =>
usageError("Missing arguments")
}
}

def parseArgsRemainder(args: List[String], scalaVersion: String, m2Repo: String, scalaIDERootOpt: Option[String]): (String, String, Option[String]) = {
args match {
case RootOption(root) :: tail =>
parseArgsRemainder(tail, scalaVersion, m2Repo, Some(root))
case Nil =>
(scalaVersion, m2Repo, scalaIDERootOpt)
case _ =>
usageError("Bad arguments")
}
}

parseArgsVersion(args, None)
}

}

class UpdateScalaIDEManifests(root: String) {
class UpdateScalaIDEManifests(scalaVersion: String, m2Repo: File, scalaIDERoot: File) {

import UpdateScalaIDEManifests._
import Ecosystem._

val rootFolder = new File(root)

def apply() {

println("Build tools: Updating versions in Scala IDE manifests.")

val scalaLibraryVersion = getPackagedBundleVersion(ScalaLibraryId)
val scalaCompilerVersion = getPackagedBundleVersion(ScalaCompilerId)
val version = getScalaVersionFromM2Repo()

projectsToUpdate foreach {
updateManifest(_, scalaLibraryVersion, scalaCompilerVersion)
updateManifest(_, new Version(version))
}

println("Build tools: Updating versions in Scala IDE manifests - Done.")

// need to stop Dispatch in any cases
Http.shutdown()
}

/**
* Returns the version contained in the generated manifest file
*/
private def getPackagedBundleVersion(projectPath: String): Version = {
val projectFolder = new File(rootFolder, projectPath)
val manifestFile = new File(projectFolder, PackagedManifestPath)
}

// TODO: check if file exists
private def getScalaVersionFromM2Repo(): String = {
val scalaLibraryJar = new File(m2Repo, s"org/scala-lang/scala-library/${scalaVersion}/scala-library-${scalaVersion}.jar")

val lines = Source.fromFile(manifestFile).getLines
val version = lines.collectFirst {
case BundleVersion(v) => v
}
val zipFile = new ZipFile(scalaLibraryJar, ZipFile.OPEN_READ)
val manifestEntry = zipFile.getEntry(PluginManifest)
val manifestInputStream = zipFile.getInputStream(manifestEntry)

// TODO: check if version found
new Version(version.get)
Source.fromInputStream(manifestInputStream, "UTF-8").getLines().collectFirst { case BundleVersion(v) => v }.get
}

/**
* Set strict version dependency to Scala library and compiler in the given project.
*/
private def updateManifest(projectPath: String, scalaLibraryVersion: Version, scalaCompilerVersion: Version) {
val projectFolder = new File(rootFolder, projectPath)
val baseManifest = new File(projectFolder, PluginManifest)
private def updateManifest(projectPath: String, scalaLibraryVersion: Version) {
val manifestFile = new File(new File(scalaIDERoot, projectPath), PluginManifest)

updateBundleManifest(baseManifest,
updateVersionInManifest(ScalaLibraryId, scalaLibraryVersion).
orElse(updateVersionInManifest(ScalaCompilerId, scalaCompilerVersion)).
updateBundleManifest(manifestFile,
updateVersionInManifest(ScalaLangLibraryId, scalaLibraryVersion).
orElse(updateVersionInManifest(ScalaLangCompilerId, scalaLibraryVersion)).
orElse {
case line =>
line
})
}

private def warning(message: String) {
println("WARNING: %s".format(message))
}

}
Loading

0 comments on commit 8a1985e

Please sign in to comment.