From 932234eb13f39a1d17b338310fb5f41997f35b7f Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Fri, 23 Jun 2017 14:55:55 +0300 Subject: BuildInfo extensions --- stage2/plugins/ExportBuildInformation.scala | 215 +++++++++++++++++----------- 1 file changed, 130 insertions(+), 85 deletions(-) diff --git a/stage2/plugins/ExportBuildInformation.scala b/stage2/plugins/ExportBuildInformation.scala index 8884ed4..8896d86 100644 --- a/stage2/plugins/ExportBuildInformation.scala +++ b/stage2/plugins/ExportBuildInformation.scala @@ -1,16 +1,12 @@ package cbt import cbt._ -import scala.xml._ -import scala.util._ import java.io._ -import scala.collection.JavaConverters._ +import scala.xml._ trait ExportBuildInformation { self: BaseBuild => - lazy val printer = new scala.xml.PrettyPrinter(200, 2) - - def buildInfoXml = - printer.format(BuildInformationSerializer.serialize(BuildInformation.Project(self))) + def buildInfoXml: String = + BuildInformationSerializer.serialize(BuildInformation.Project(self)).toString } object BuildInformation { @@ -19,7 +15,9 @@ object BuildInformation { root: File, rootModule: Module, modules: Seq[Module], - libraries: Seq[Library] + libraries: Seq[Library], + cbtLibraries: Seq[Library], + scalaCompilers: Seq[ScalaCompiler] ) case class Module( @@ -30,8 +28,9 @@ object BuildInformation { target: File, binaryDependencies: Seq[BinaryDependency], moduleDependencies: Seq[ModuleDependency], - classpaths: Seq[ClassPathItem], - parentBuild: Option[String] + classpath: Seq[File], + parentBuild: Option[String], + scalacOptions: Seq[String] ) case class Library( name: String, jars: Seq[File] ) @@ -40,162 +39,208 @@ object BuildInformation { case class ModuleDependency( name: String ) - case class ClassPathItem( path: File ) + case class ScalaCompiler( version: String, jars: Seq[File] ) object Project { - def apply(build: BaseBuild) = - new BuildInformationExporter(build).exportBuildInformation + def apply(build: BaseBuild): Project = + new BuildInformationExporter(build).exportBuildInformation class BuildInformationExporter(rootBuild: BaseBuild) { - def exportBuildInformation(): Project = { + def exportBuildInformation: Project = { val moduleBuilds = transitiveBuilds(rootBuild) val libraries = moduleBuilds .flatMap(_.transitiveDependencies) .collect { case d: BoundMavenDependency => exportLibrary(d) } .distinct val cbtLibraries = convertCbtLibraries - val cbtbinaryDependencies = cbtLibraries - .map(l => BinaryDependency(l.name)) - val rootModule = exportModule(cbtbinaryDependencies)(rootBuild) - val modules = moduleBuilds.map(exportModule(cbtbinaryDependencies)) + val rootModule = exportModule(rootBuild) + val modules = moduleBuilds + .map(exportModule) + .distinct + + val scalaCompilers = modules + .map(_.scalaVersion) + .map(v => ScalaCompiler(v, scalaCompiler(rootBuild, v))) + Project( rootModule.name, rootModule.root, rootModule, modules, - libraries ++ cbtLibraries + libraries, + cbtLibraries, + scalaCompilers ) } - private def convertCbtLibraries() = + private def convertCbtLibraries = transitiveBuilds(DirectoryDependency(rootBuild.context.cbtHome)(rootBuild.context).dependenciesArray.head.asInstanceOf[BaseBuild]) - .collect { - case d: BoundMavenDependency => d.jar - case d: PackageJars => d.jar.get - } - .map(exportLibrary) - .distinct - - private def collectLazyBuilds(dependency: Dependency): Option[BaseBuild] = + .collect { + case d: BoundMavenDependency => d.jar + case d: PackageJars => d.jar.get + } + .map(exportLibrary) + .distinct + + private def collectLazyBuilds(dependency: Dependency): Option[BaseBuild] = dependency match { - case l: LazyDependency => + case l: LazyDependency => l.dependency match { - case d: BaseBuild => Some(d) - case d: LazyDependency => collectLazyBuilds(d.dependency) - case _ => None + case d: BaseBuild => Some(d) + case d: LazyDependency => collectLazyBuilds(d.dependency) + case _ => None } case d: BaseBuild => Some(d) case _ => None } - private def transitiveBuilds(build: BaseBuild): Seq[BaseBuild] = + private def transitiveBuilds(build: BaseBuild): Seq[BaseBuild] = (build +: build.transitiveDependencies) - .collect { - case d: BaseBuild => d +: collectParentBuilds(d).flatMap(transitiveBuilds) - case d: LazyDependency => - collectLazyBuilds(d.dependency) - .toSeq - .flatMap(transitiveBuilds) - } - .flatten - .distinct + .collect { + case d: BaseBuild => d +: collectParentBuilds(d).flatMap(transitiveBuilds) + case d: LazyDependency => + collectLazyBuilds(d.dependency) + .toSeq + .flatMap(transitiveBuilds) + } + .flatten + .distinct - private def exportLibrary(mavenDependency: BoundMavenDependency) = - Library(fomatMavenDependency(mavenDependency.mavenDependency), mavenDependency.exportedJars) + private def exportLibrary(mavenDependency: BoundMavenDependency) = { + val name = formatMavenDependency(mavenDependency.mavenDependency) + val jars = (mavenDependency +: mavenDependency.transitiveDependencies) + .map(_.asInstanceOf[BoundMavenDependency].jar) + Library(name, jars) + } - private def exportLibrary(file: File) = + private def exportLibrary(file: File) = Library("CBT:" + file.getName.stripSuffix(".jar"), Seq(file)) - private def collectParentBuilds(build: BaseBuild): Seq[BaseBuild] = + private def collectParentBuilds(build: BaseBuild): Seq[BaseBuild] = build.context.parentBuild - .map(_.asInstanceOf[BaseBuild]) - .map(b => b +: collectParentBuilds(b)) - .toSeq - .flatten - - private def exportModule(cbtbinaryDependencies: Seq[BinaryDependency])(build: BaseBuild): Module = { - def collectDependencies(dependencies: Seq[Dependency]): Seq[ModuleDependency] = - dependencies + .map(_.asInstanceOf[BaseBuild]) + .map(b => b +: collectParentBuilds(b)) + .toSeq + .flatten + + private def collectDependencies(dependencies: Seq[Dependency]): Seq[ModuleDependency] = + dependencies .collect { - case d: BaseBuild => Seq(ModuleDependency(moduleName(d))) - case d: LazyDependency => collectDependencies(Seq(d.dependency)) - } - .flatten + case d: BaseBuild => Seq(ModuleDependency(moduleName(d))) + case d: LazyDependency => collectDependencies(Seq(d.dependency)) + } + .flatten + + private def exportModule(build: BaseBuild): Module = { val moduleDependencies = collectDependencies(build.dependencies) val mavenDependencies = build.dependencies - .collect { case d: BoundMavenDependency => BinaryDependency(fomatMavenDependency(d.mavenDependency))} - val classpaths = build.dependencyClasspath.files + .collect { case d: BoundMavenDependency => BinaryDependency(formatMavenDependency(d.mavenDependency)) } + val classpath = build.dependencyClasspath.files .filter(_.isFile) - .map(t => ClassPathItem(t)) - val sources = build.sources - .filter(s => s.exists && s.isDirectory) :+ build.projectDirectory - + .distinct + val sources = { + val s = build.sources + .filter(_.exists) + .map(handleSource) + .filter(_.getName != "target") //Dirty hack for cbt's sources + .distinct + if (s.nonEmpty) + s + else + Seq(build.projectDirectory) + } + Module( name = moduleName(build), root = build.projectDirectory, scalaVersion = build.scalaVersion, sources = sources, target = build.target, - binaryDependencies = mavenDependencies ++ cbtbinaryDependencies, + binaryDependencies = mavenDependencies, moduleDependencies = moduleDependencies, - classpaths = classpaths, - parentBuild = build.context.parentBuild.map(b => moduleName(b.asInstanceOf[BaseBuild])) + classpath = classpath, + parentBuild = build.context.parentBuild.map(b => moduleName(b.asInstanceOf[BaseBuild])), + scalacOptions = build.scalacOptions ) } - private def fomatMavenDependency(dependency: cbt.MavenDependency) = + private def scalaCompiler(build: BaseBuild, scalaVersion: String) = + build.Resolver(mavenCentral, sonatypeReleases).bindOne( + MavenDependency("org.scala-lang", "scala-compiler", scalaVersion) + ).classpath.files + + + private def handleSource(source: File): File = + if (source.isDirectory) + source + else + source.getParentFile //Let's asume that for now + + + private def formatMavenDependency(dependency: cbt.MavenDependency) = s"${dependency.groupId}:${dependency.artifactId}:${dependency.version}" - private def moduleName(build: BaseBuild) = + private def moduleName(build: BaseBuild) = if (rootBuild.projectDirectory == build.projectDirectory) rootBuild.projectDirectory.getName else build.projectDirectory.getPath - .drop(rootBuild.projectDirectory.getPath.length) - .stripPrefix("/") - .replace("/", "-") + .drop(rootBuild.projectDirectory.getPath.length) + .stripPrefix("/") + .replace("/", "-") } } } object BuildInformationSerializer { - def serialize(project: BuildInformation.Project): Node = - + def serialize(project: BuildInformation.Project): Node = + {project.modules.map(serialize)} {project.libraries.map(serialize)} + + {project.cbtLibraries.map(serialize)} + + + {project.scalaCompilers.map(serialize)} + - private def serialize(module: BuildInformation.Module): Node = + private def serialize(module: BuildInformation.Module): Node = {module.sources.map(s => {s})} + + {module.scalacOptions.map(o => )} + - {module.binaryDependencies.map(serialize)} + {module.binaryDependencies.map(serialize)} {module.moduleDependencies.map(serialize)} - {module.classpaths.map(serialize)} + {module.classpath.map(c => {c.toString})} {module.parentBuild.map(p => {p}).getOrElse(NodeSeq.Empty)} - private def serialize(binaryDependency: BuildInformation.BinaryDependency): Node = + private def serialize(binaryDependency: BuildInformation.BinaryDependency): Node = {binaryDependency.name} - private def serialize(library: BuildInformation.Library): Node = - + private def serialize(library: BuildInformation.Library): Node = + {library.jars.map(j => {j})} - private def serialize(moduleDependency: BuildInformation.ModuleDependency): Node = - {moduleDependency.name} + private def serialize(compiler: BuildInformation.ScalaCompiler): Node = + + {compiler.jars.map(j => {j})} + - private def serialize(targetLibrary: BuildInformation.ClassPathItem): Node = - {targetLibrary.path.toString} -} + private def serialize(moduleDependency: BuildInformation.ModuleDependency): Node = + {moduleDependency.name} +} \ No newline at end of file -- cgit v1.2.3 From b3d5c8a0230d7068a7d8c60063b08fed16783e5f Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Sat, 24 Jun 2017 17:50:35 +0300 Subject: Rename sources to sourceDirs --- stage2/plugins/ExportBuildInformation.scala | 96 ++++++++++++++--------------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/stage2/plugins/ExportBuildInformation.scala b/stage2/plugins/ExportBuildInformation.scala index 8896d86..6a22363 100644 --- a/stage2/plugins/ExportBuildInformation.scala +++ b/stage2/plugins/ExportBuildInformation.scala @@ -24,7 +24,7 @@ object BuildInformation { name: String, root: File, scalaVersion: String, - sources: Seq[File], + sourceDirs: Seq[File], target: File, binaryDependencies: Seq[BinaryDependency], moduleDependencies: Seq[ModuleDependency], @@ -57,10 +57,9 @@ object BuildInformation { val modules = moduleBuilds .map(exportModule) .distinct - val scalaCompilers = modules .map(_.scalaVersion) - .map(v => ScalaCompiler(v, scalaCompiler(rootBuild, v))) + .map(v => ScalaCompiler(v, resolveScalaCompiler(rootBuild, v))) Project( rootModule.name, @@ -82,6 +81,47 @@ object BuildInformation { .map(exportLibrary) .distinct + private def collectDependencies(dependencies: Seq[Dependency]): Seq[ModuleDependency] = + dependencies + .collect { + case d: BaseBuild => Seq(ModuleDependency(moduleName(d))) + case d: LazyDependency => collectDependencies(Seq(d.dependency)) + } + .flatten + + private def exportModule(build: BaseBuild): Module = { + val moduleDependencies = collectDependencies(build.dependencies) + val mavenDependencies = build.dependencies + .collect { case d: BoundMavenDependency => BinaryDependency(formatMavenDependency(d.mavenDependency)) } + val classpath = build.dependencyClasspath.files + .filter(_.isFile) + .distinct + val sourceDirs = { + val s = build.sources + .filter(_.exists) + .map(handleSource) + .filter(_.getName != "target") //Dirty hack for cbt's sources + .distinct + if (s.nonEmpty) + s + else + Seq(build.projectDirectory) + } + + Module( + name = moduleName(build), + root = build.projectDirectory, + scalaVersion = build.scalaVersion, + sourceDirs = sourceDirs, + target = build.target, + binaryDependencies = mavenDependencies, + moduleDependencies = moduleDependencies, + classpath = classpath, + parentBuild = build.context.parentBuild.map(b => moduleName(b.asInstanceOf[BaseBuild])), + scalacOptions = build.scalacOptions + ) + } + private def collectLazyBuilds(dependency: Dependency): Option[BaseBuild] = dependency match { case l: LazyDependency => @@ -124,53 +164,11 @@ object BuildInformation { .toSeq .flatten - private def collectDependencies(dependencies: Seq[Dependency]): Seq[ModuleDependency] = - dependencies - .collect { - case d: BaseBuild => Seq(ModuleDependency(moduleName(d))) - case d: LazyDependency => collectDependencies(Seq(d.dependency)) - } - .flatten - - private def exportModule(build: BaseBuild): Module = { - val moduleDependencies = collectDependencies(build.dependencies) - val mavenDependencies = build.dependencies - .collect { case d: BoundMavenDependency => BinaryDependency(formatMavenDependency(d.mavenDependency)) } - val classpath = build.dependencyClasspath.files - .filter(_.isFile) - .distinct - val sources = { - val s = build.sources - .filter(_.exists) - .map(handleSource) - .filter(_.getName != "target") //Dirty hack for cbt's sources - .distinct - if (s.nonEmpty) - s - else - Seq(build.projectDirectory) - } - - Module( - name = moduleName(build), - root = build.projectDirectory, - scalaVersion = build.scalaVersion, - sources = sources, - target = build.target, - binaryDependencies = mavenDependencies, - moduleDependencies = moduleDependencies, - classpath = classpath, - parentBuild = build.context.parentBuild.map(b => moduleName(b.asInstanceOf[BaseBuild])), - scalacOptions = build.scalacOptions - ) - } - - private def scalaCompiler(build: BaseBuild, scalaVersion: String) = + private def resolveScalaCompiler(build: BaseBuild, scalaVersion: String) = build.Resolver(mavenCentral, sonatypeReleases).bindOne( MavenDependency("org.scala-lang", "scala-compiler", scalaVersion) ).classpath.files - private def handleSource(source: File): File = if (source.isDirectory) source @@ -212,9 +210,9 @@ object BuildInformationSerializer { private def serialize(module: BuildInformation.Module): Node = - - {module.sources.map(s => {s})} - + + {module.sourceDirs.map(d => {d})} + {module.scalacOptions.map(o => )} -- cgit v1.2.3 From 76c5cd2135cf78e503f40cf9192d0302cd4cec90 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Sat, 24 Jun 2017 19:00:29 +0300 Subject: Filter common childs in dirs --- stage2/plugins/ExportBuildInformation.scala | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/stage2/plugins/ExportBuildInformation.scala b/stage2/plugins/ExportBuildInformation.scala index 6a22363..be61609 100644 --- a/stage2/plugins/ExportBuildInformation.scala +++ b/stage2/plugins/ExportBuildInformation.scala @@ -2,6 +2,7 @@ package cbt import cbt._ import java.io._ +import java.nio.file._ import scala.xml._ trait ExportBuildInformation { self: BaseBuild => @@ -100,10 +101,8 @@ object BuildInformation { val s = build.sources .filter(_.exists) .map(handleSource) - .filter(_.getName != "target") //Dirty hack for cbt's sources - .distinct if (s.nonEmpty) - s + commonParents(s) else Seq(build.projectDirectory) } @@ -122,6 +121,21 @@ object BuildInformation { ) } + private def commonParents(paths: Seq[File]): Seq[File] = { //Too slow O(n^2) + val buffer = scala.collection.mutable.ListBuffer.empty[Path] + val sorted = paths + .map(_.toPath.toAbsolutePath) + .sortWith(_.getNameCount < _.getNameCount) + for (x <- sorted) { + if (!buffer.exists(x.startsWith)) { + buffer += x + } + } + buffer + .toList + .map(_.toFile) + } + private def collectLazyBuilds(dependency: Dependency): Option[BaseBuild] = dependency match { case l: LazyDependency => -- cgit v1.2.3