Skip to content
This repository
tree: 7f9526f75c
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 262 lines (223 sloc) 10.817 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
import sbt._
import Keys._

// I need to make these imported by default
import Project.inConfig
import Configurations.config
import Build.data
import Path._
import sbtassembly.Plugin.AssemblyKeys
import sbtassembly.Plugin.AssemblyKeys._
import sbtassembly.Plugin.assemblySettings
import sbtassembly.Plugin.MergeStrategy
import sbtbuildinfo.Plugin._

object BuildSettings {
  
  val buildName = "mima"
  val buildOrganization = "com.typesafe"

  val buildScalaVer = "2.9.2"
  val buildVersion = "0.1.5-SNAPSHOT"

  val commonSettings = Defaults.defaultSettings ++ Seq (
      organization := buildOrganization,
      scalaVersion := buildScalaVer,
      version := buildVersion,
      licenses := Seq("Apache License v2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")),
      homepage := Some(url("http://github.com/typesafehub/migration-manager"))
  )


  def sbtPublishSettings: Seq[Setting[_]] = Seq(
    publishMavenStyle := false,
    publishTo <<= (version) { version: String =>
       val scalasbt = " "
       val (name, u) = if (version.contains("-SNAPSHOT")) ("sbt-plugin-snapshots", scalasbt+"sbt-plugin-snapshots")
                       else ("sbt-plugin-releases", scalasbt+"sbt-plugin-releases")
       Some(Resolver.url(name, url(u))(Resolver.ivyStylePatterns))
    }
  )

  def sonatypePublishSettings: Seq[Setting[_]] = Seq(
    // If we want on maven central, we need to be in maven style.
    publishMavenStyle := true,
    publishArtifact in Test := false,
    // The Nexus repo we're publishing to.
    publishTo <<= version { (v: String) =>
      val nexus = "https://oss.sonatype.org/"
      if (v.trim.endsWith("SNAPSHOT")) Some("snapshots" at nexus + "content/repositories/snapshots")
      else Some("releases" at nexus + "service/local/staging/deploy/maven2")
    },
    // Maven central cannot allow other repos. We're ok here because the artifacts we
    // we use externally are *optional* dependencies.
    pomIncludeRepository := { x => false },
    // Maven central wants some extra metadata to keep things 'clean'.
    pomExtra := (
      <scm>
        <url>git@github.com:typesafehub/migration-manager.git</url>
        <connection>scm:git:git@github.com:typesafehub/migration-manager.git</connection>
      </scm>
      <developers>
        <developer>
          <id>mdotta</id>
          <name>Mirco Dotta</name>
        </developer>
        <developer>
          <id>jsuereth</id>
          <name>Josh Suereth</name>
          <url>http://jsuereth.com</url>
        </developer>
      </developers>)
  )
}

object Dependencies {
  import BuildSettings._
  
  val compiler = "org.scala-lang" % "scala-compiler" % buildScalaVer
  val swing = "org.scala-lang" % "scala-swing" % buildScalaVer
  
  val specs2 = "org.specs2" % "specs2_2.9.1" % "1.5" % "test"
}

object MimaBuild extends Build {
  import BuildSettings._
  import Dependencies._

  // here we list all projects that are defined.
  override lazy val projects = Seq(root) ++ modules ++ tests :+ reporterFunctionalTests
  
  lazy val modules = Seq(core, coreui, reporter, reporterui, sbtplugin)

  lazy val root = (
    Project("root", file("."), aggregate = modules.map(Reference.projectToRef(_)))
    settings(publish := (),
             publishLocal := ())
  )

  lazy val core = (
    Project("core", file("core"),
            settings = commonSettings ++: buildInfoSettings ++: Seq(
                sourceGenerators in Compile <+= buildInfo,
                buildInfoKeys := Seq[Scoped](version),
                buildInfoPackage := "com.typesafe.tools.mima.core.buildinfo",
                buildInfoObject := "BuildInfo"
                )
           )
    settings(libraryDependencies ++= Seq(compiler, specs2),
             name := buildName + "-core")
    settings(sonatypePublishSettings:_*)
  )

  lazy val coreui = (
    Project("core-ui", file("core-ui"), settings = commonSettings)
    settings(libraryDependencies ++= Seq(swing, compiler, specs2),
             name := buildName + "-core-ui")
    dependsOn(core)
    settings(sonatypePublishSettings:_*)
  )

  val myAssemblySettings: Seq[Setting[_]] = assemblySettings ++ Seq(
     mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
        {
          case "LICENSE" => MergeStrategy.first
          case x => old(x)
        }
     },
     AssemblyKeys.excludedFiles in assembly <<= (AssemblyKeys.excludedFiles in assembly) { (old) =>
       val tmp: Seq[File] => Seq[File] = { files: Seq[File] =>
         // Hack to keep LICENSE files.
         old(files) filterNot (_.getName contains "LICENSE")
       }
       tmp
     }
  )

  lazy val reporter = (
    Project("reporter", file("reporter"), settings = commonSettings)
    settings(libraryDependencies ++= Seq(swing),
             name := buildName + "-reporter",
             javaOptions += "-Xmx512m")
    dependsOn(core)
    settings(sonatypePublishSettings:_*)
    settings(myAssemblySettings:_*)
    settings(
      // add task functional-tests that depends on all functional tests
      functionalTests <<= runAllTests,
      // make the main 'package' task depend on all functional tests passing (TODO - Control this in root project...)
      packageBin in Compile <<= packageBin in Compile dependsOn functionalTests,
      mainClass in assembly := Some("com.typesafe.tools.mima.cli.Main")
    )
  )

  lazy val reporterui = (
    Project("reporter-ui", file("reporter-ui"), settings = commonSettings)
    settings(myAssemblySettings:_*)
    settings(sonatypePublishSettings:_*)
    settings(libraryDependencies ++= Seq(swing),
             name := buildName + "-reporter-ui",
             javaOptions += "-Xmx512m",
             mainClass in assembly := Some("com.typesafe.tools.mima.lib.ui.MimaLibApp"))
    dependsOn(coreui, reporter)
  )

  lazy val sbtplugin = (
     Project("sbtplugin", file("sbtplugin"), settings = commonSettings)
     settings(name := "sbt-mima-plugin",
              sbtPlugin := true)
     dependsOn(reporter)
    settings(sbtPublishSettings:_*)
  )

  lazy val reporterFunctionalTests = Project("reporter-functional-tests",
   file("reporter") / "functional-tests" ,
   settings = commonSettings)
   .dependsOn(core, reporter)

  // select all testN directories.
  val bases = (file("reporter") / "functional-tests" / "src" / "test") * (DirectoryFilter)

  // make the Project for each discovered directory
  lazy val tests = bases.getFiles map testProject

  // defines a Project for the given base directory (for example, functional-tests/test1)
  // Its name is the directory name (test1) and it has compile+package tasks for sources in v1/ and v2/
  def testProject(base: File) = Project(base.name, base, settings = testProjectSettings)
   .configs(v1Config, v2Config) dependsOn (reporterFunctionalTests)

  lazy val testProjectSettings =
    commonSettings ++ // normal project defaults; can be trimmed later- test and run aren't needed, for example.
      inConfig(v1Config)(perConfig) ++ // add compile/package for the v1 sources
      inConfig(v2Config)(perConfig) :+ // add compile/package for the v2 sources
      (functionalTests <<= runTest) // add the functional-tests task.

  // this is the key for the task that runs the reporter's functional tests
  lazy val functionalTests = TaskKey[Unit]("test-functional")

  // define configurations for the v1 and v2 sources
  lazy val v1Config = config("v1") extend Compile
  lazy val v2Config = config("v2") extend Compile

  // these are settings defined for each configuration (v1 and v2).
  // We use the normal per-configuration settings, but modify the source directory to be just v1/ instead of src/v1/scala/
  lazy val perConfig = Defaults.configSettings :+ shortSourceDir

  // sets the source directory in this configuration to be: testN / vN
  // scalaSource is the setting key that defines the directory for Scala sources
  // configuration gets the current configuration
  // expanded version: ss <<= (bd, conf) apply { (b,c) => b / c.name }
  lazy val shortSourceDir = scalaSource <<= (baseDirectory, configuration) { _ / _.name }

  // this is the custom test task of the form (ta, tb, tc) map { (a,b,c) => ... }
  // tx are the tasks we need to do our job.
  // Once the task engine runs these tasks, it evaluates the function supplied to map with the task results bound to
  // a,b,c
  lazy val runTest =
    (fullClasspath in (reporterFunctionalTests, Compile), // the test classpath from the functionalTest project for the test
      thisProjectRef, // gives us the ProjectRef this task is defined in
      scalaInstance, // get a reference to the already loaded Scala classes so we get the advantage of a warm jvm
      packageBin in v1Config, // package the v1 sources and get the configuration used
      packageBin in v2Config, // same for v2
      streams) map { (cp, proj, si, v1, v2, streams) =>
        val urls = data(cp).map(_.toURI.toURL).toArray
        val loader = new java.net.URLClassLoader(urls, si.loader)

        val testClass = loader.loadClass("com.typesafe.tools.mima.lib.CollectProblemsTest")
        val testRunner = testClass.newInstance().asInstanceOf[{
          def runTest(testClasspath: Array[String], testName: String, oldJarPath: String, newJarPath: String, oraclePath: String): Unit
        }]

        // Add the scala-library to the MiMa classpath used to run this test
        val testClasspath = data(cp).filter(_.getName endsWith "scala-library.jar").map(_.getAbsolutePath).toArray

        val projectPath = proj.build.getPath + "reporter" + "/" + "functional-tests" + "/" + "src" + "/" + "test" + "/" + proj.project

        val oraclePath = projectPath + "/problems.txt"

        try {
          testRunner.runTest(testClasspath, proj.project, v1.getAbsolutePath, v2.getAbsolutePath, oraclePath)
          streams.log.info("Test '" + proj.project + "' succeeded.")
        } catch {
          case e: Exception => streams.log.error(e.toString)
        }
        ()
      }

  lazy val runAllTests =
    (state, // this is how we access all defined projects from a task
      thisProjectRef, // gives us the ProjectRef this task is defined in
      test in Test // requires unit tests to run first
      ) flatMap { (s, proj, _) =>
        // gets all defined projects, dropping this project (core) so the task doesn't depend on itself
        val structure = Project.structure(s)
        val allProjects = structure.units(proj.build).defined.values filter (_.id != proj.project)
        // get the fun-tests task in each project
        val allTests = allProjects.toSeq flatMap { p => functionalTests in ProjectRef(proj.build, p.id) get structure.data }
        // depend on all fun-tests
        allTests.join.map(_ => ())
      }

}
Something went wrong with that request. Please try again.