package cbt import cbt._ import scala.xml._ import java.io._ trait ExportBuildInformation { self: BaseBuild => lazy val printer = new scala.xml.PrettyPrinter(200, 2) def buildInfoXml = printer.format(BuildInformationSerializer.serialize(BuildInformation.Project(self))) } object BuildInformation { case class Project( name: String, root: File, rootModule: Module, modules: Seq[Module], libraries: Seq[Library] ) case class Module( name: String, root: File, sources: Seq[File], target: File, mavenDependencies: Seq[MavenDependency], moduleDependencies: Seq[ModuleDependency], classpaths: Seq[ClassPathItem], parentBuild: Option[String] ) case class Library( name: String, jars: Seq[File] ) case class MavenDependency( name: String ) case class ModuleDependency( name: String ) case class ClassPathItem( path: File ) object Project { def apply(build: BaseBuild) = new BuildInformationExporter(build).exportBuildInformation private class BuildInformationExporter(rootBuild: BaseBuild) { def exportBuildInformation(): Project = { val rootModule = exportModule(rootBuild) val modules = (rootBuild +: rootBuild.transitiveDependencies) .collect { case d: BaseBuild => d +: collectParentBuilds(d)} .flatten .map(exportModule) .distinct val libraries = rootBuild.transitiveDependencies .collect { case d: BoundMavenDependency => exportLibrary(d)} .distinct Project( rootModule.name, rootModule.root, rootModule, modules, libraries ) } private def exportLibrary(mavenDependency: BoundMavenDependency) = Library(fomatMavenDependency(mavenDependency.mavenDependency), mavenDependency.exportedJars) private def collectParentBuilds(build: BaseBuild): Seq[BaseBuild] = build.context.parentBuild .map(_.asInstanceOf[BaseBuild]) .map(b => b +: collectParentBuilds(b)) .toSeq .flatten private def exportModule(build: BaseBuild): Module = { val moduleDependencies = build.dependencies .collect { case d: BaseBuild => ModuleDependency(moduleName(d)) } val mavenDependencies = build.dependencies .collect { case d: BoundMavenDependency => MavenDependency(fomatMavenDependency(d.mavenDependency))} val classpaths = build.dependencyClasspath.files .filter(_.isFile) .map(t => ClassPathItem(t)) val sources = { val s = build.sources .filter(s => s.exists && s.isDirectory) if (s.isEmpty) Seq(build.projectDirectory) else s } Module( name = moduleName(build), root = build.projectDirectory, sources = sources, target = build.target, mavenDependencies = mavenDependencies, moduleDependencies = moduleDependencies, classpaths = classpaths, parentBuild = build.context.parentBuild.map(b => moduleName(b.asInstanceOf[BaseBuild])) ) } private def fomatMavenDependency(dependency: cbt.MavenDependency) = s"${dependency.groupId}:${dependency.artifactId}:${dependency.version}" private def moduleName(build: BaseBuild) = if (rootBuild.projectDirectory == build.projectDirectory) rootBuild.projectDirectory.getName else build.projectDirectory.getPath .drop(rootBuild.projectDirectory.getPath.length) .stripPrefix("/") .replace("/", "-") } } } object BuildInformationSerializer { def serialize(project: BuildInformation.Project): Node = {project.name} {project.root.toString} {project.rootModule.name} {project.modules.map(serialize)} {project.libraries.map(serialize)} private def serialize(module: BuildInformation.Module): Node = {module.name} {module.root} {module.target} {module.sources.map(s => {s})} {module.mavenDependencies.map(serialize)} {module.moduleDependencies.map(serialize)} {module.classpaths.map(serialize)} {module.parentBuild.map(p => {p}).getOrElse(NodeSeq.Empty)} private def serialize(mavenDependency: BuildInformation.MavenDependency): Node = {mavenDependency.name} private def serialize(library: BuildInformation.Library): Node = {library.name} {library.jars.map(j => {j})} private def serialize(moduleDependency: BuildInformation.ModuleDependency): Node = {moduleDependency.name} private def serialize(targetLibrary: BuildInformation.ClassPathItem): Node = {targetLibrary.path.toString} }