|
| 1 | +package scalabuild |
| 2 | + |
| 3 | +import java.io.FileWriter |
| 4 | +import java.util.Properties |
| 5 | + |
| 6 | +import sbt._ |
| 7 | +import Keys._ |
| 8 | + |
| 9 | +object JitWatchFilePlugin extends AutoPlugin { |
| 10 | + override def trigger = allRequirements |
| 11 | + override def requires = sbt.plugins.JvmPlugin |
| 12 | + val jitwatchConfigFileContents = taskKey[Properties]("Contents of file suitable for `jitwatch/launchUI -Djitwatch.config.file=jitwatch.properties`") |
| 13 | + val jitwatchConfigFile = taskKey[Unit]("file suitable for `jitwatch/launchUI.sh -Djitwatch.config.file=jitwatch.properties`") |
| 14 | + |
| 15 | + override lazy val projectSettings = List(Compile, Test).flatMap(c => inConfig(c)(jitwatchSettings)) |
| 16 | + |
| 17 | + def jitwatchSettings: Seq[Setting[_]] = Seq( |
| 18 | + jitwatchConfigFileContents := { |
| 19 | + val sourcesValue = sources.value |
| 20 | + val depdependencyClasspathValue = dependencyClasspath.value ++ internalDependencyClasspath.value |
| 21 | + val props = new java.util.Properties |
| 22 | + val classpathString = (classDirectory.value +: depdependencyClasspathValue.map(_.data.toString)).mkString(",") |
| 23 | + val artifacts: Seq[Artifact] = depdependencyClasspathValue.flatMap(_.get(Keys.artifact.key)) |
| 24 | + val dependencyModuleIds: Set[ModuleID] = depdependencyClasspathValue.flatMap(_.get(Keys.moduleID.key)).toSet |
| 25 | + props.put("Classes", classpathString) |
| 26 | + |
| 27 | + // JDK sources from $JAVA_HOME/src.zip |
| 28 | + val javaHomeSrc = { |
| 29 | + val javaDir = javaHome.value.getOrElse(new File(System.getProperty("java.home"))) |
| 30 | + val src1 = javaDir / "src.zip" |
| 31 | + val src2 = javaDir.getParentFile / "src.zip" |
| 32 | + if (src1.exists()) src1 else src2 |
| 33 | + } |
| 34 | + |
| 35 | + // Transitive sources from the projects that contribute to this classpath. |
| 36 | + val projects: Seq[ProjectRef] = buildDependencies.value.classpathTransitiveRefs(thisProjectRef.value) :+ thisProjectRef.value |
| 37 | + val projectArtifacts: Map[ProjectRef, Seq[Artifact]] = projects.map(project => (project -> (Keys.artifacts in project get settingsData.value).getOrElse(Nil))).toMap |
| 38 | + val artifactNameToProject: Map[String, Seq[ProjectRef]] = projects.groupBy(project => (Keys.name in project get settingsData.value).getOrElse("")) |
| 39 | + val transitiveSourceDirectories = projects.flatMap { project => |
| 40 | + val projectArtifacts: Seq[Artifact] = (Keys.artifacts in project get settingsData.value).getOrElse(Nil) |
| 41 | + val matching = projectArtifacts.filter(artifacts.contains(_)) |
| 42 | + val configs = matching.flatMap(artifact => artifact.configurations).distinct |
| 43 | + val sourceDirectories: Seq[File] = configs.flatMap { configRef => |
| 44 | + (Keys.sourceDirectories in project in sbt.Configuration.of(configRef.name.capitalize, configRef.name)).get(settingsData.value).toList.flatten |
| 45 | + } |
| 46 | + sourceDirectories |
| 47 | + }.distinct |
| 48 | + val transitiveSourceDirectories2 = artifacts.flatMap { artifact => |
| 49 | + val projects = artifactNameToProject.getOrElse(artifact.name, Nil) |
| 50 | + projects.flatMap { project: ProjectRef => |
| 51 | + val configs = artifact.configurations |
| 52 | + val sourceDirectories: Seq[File] = configs.toList.flatMap { configRef => |
| 53 | + (Keys.sourceDirectories in project in sbt.Configuration.of(configRef.name.capitalize, configRef.name)).get(settingsData.value).toList.flatten |
| 54 | + } |
| 55 | + sourceDirectories |
| 56 | + } |
| 57 | + } |
| 58 | + |
| 59 | + // Download and add transitive sources from the classpath |
| 60 | + val classiferArtifacts: Seq[(ModuleID, Artifact, File)] = updateClassifiers.value.configurations.flatMap(_.details.flatMap(_.modules.flatMap(report => report.artifacts.map(x => (report.module, x._1, x._2))))) |
| 61 | + val sourceClassiferArtifacts = classiferArtifacts.filter(tuple => tuple._2.classifier == Some("sources") && dependencyModuleIds.contains(tuple._1)) |
| 62 | + |
| 63 | + val externalSources = sourceClassiferArtifacts.map(_._3) |
| 64 | + val internalAndExternalSources = (sourceDirectory.value +: javaHomeSrc +: (transitiveSourceDirectories ++ transitiveSourceDirectories2).distinct) ++ externalSources |
| 65 | + props.put("Sources", internalAndExternalSources.map(_.getAbsolutePath).mkString(",")) |
| 66 | + val baseDir = baseDirectory.value |
| 67 | + val lastLogDir = Keys.forkOptions.value.workingDirectory match { |
| 68 | + case Some(dir) => dir |
| 69 | + case _=> baseDir |
| 70 | + } |
| 71 | + props.put("LastLogDir", lastLogDir.getAbsolutePath) |
| 72 | + props |
| 73 | + }, |
| 74 | + |
| 75 | + jitwatchConfigFile := { |
| 76 | + val f = target.value / ("jitwatch-" + configuration.value.name + ".properties") |
| 77 | + val contents = jitwatchConfigFileContents.value |
| 78 | + val log = streams.value.log |
| 79 | + val fw = new FileWriter(f) |
| 80 | + try { |
| 81 | + jitwatchConfigFileContents.value.store(fw, null) |
| 82 | + log.info(s"./launchUI.sh -Djitwatch.config.file=" + f.getAbsolutePath) |
| 83 | + } finally { |
| 84 | + fw.close() |
| 85 | + } |
| 86 | + } |
| 87 | + ) |
| 88 | +} |
0 commit comments