diff options
author | dos65 <qtankle@gmail.com> | 2017-11-28 01:56:42 +0300 |
---|---|---|
committer | Nikolay Tatarinov <5min4eq.unity@gmail.com> | 2017-12-20 01:17:16 +0300 |
commit | 6a7f6cf910362cadf6b39f8c0795c46745e08742 (patch) | |
tree | 5473fc949137771ab3f82cc259a83fb0966555f5 /scalaplugin | |
parent | 2ecfb282365f7fd8168bfb845cdbb403c00e9615 (diff) | |
download | mill-6a7f6cf910362cadf6b39f8c0795c46745e08742.tar.gz mill-6a7f6cf910362cadf6b39f8c0795c46745e08742.tar.bz2 mill-6a7f6cf910362cadf6b39f8c0795c46745e08742.zip |
publishLocal - looks like it works
Diffstat (limited to 'scalaplugin')
6 files changed, 355 insertions, 6 deletions
diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala index ce7b5e00..f7cb8963 100644 --- a/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala +++ b/scalaplugin/src/main/scala/mill/scalaplugin/ScalaModule.scala @@ -198,13 +198,37 @@ trait ScalaModule extends Module with TaskModule{ outer => Seq(resources(), compile().classes)).map(_.path).filter(exists) } def assembly = T{ - createAssembly(assemblyClasspath(), prependShellScript = prependShellScript()) + val outDir = T.ctx().dest/up + val n = name() + val v = version() + val jarName = s"${n}-${v}.jar" + val dest = outDir/jarName + createAssembly(dest, assemblyClasspath(), prependShellScript = prependShellScript()) } def classpath = T{ Seq(resources(), compile().classes) } def jar = T{ - createJar(Seq(resources(), compile().classes).map(_.path).filter(exists), mainClass()) + val outDir = T.ctx().dest/up + val n = name() + val v = version() + val jarName = s"${n}-${v}.jar" + val dest = outDir/jarName + createJar(dest, Seq(resources(), compile().classes).map(_.path).filter(exists), mainClass()) + PathRef(dest) + } + + def sourcesJar = T{ + val outDir = T.ctx().dest/up + val n = name() + val v = version() + val jarName = s"${n}-${v}-sources.jar" + val dest = outDir/jarName + + val inputs = Seq(sources(), resources()).map(_.path).filter(exists) + + createJar(dest, inputs) + PathRef(dest) } def run() = T.command{ @@ -223,6 +247,27 @@ trait ScalaModule extends Module with TaskModule{ outer => options = Seq("-usejavacp") ) } + + def organization: T[String] = "acme" + def name: T[String] = pwd.last.toString + def version: T[String] = "0.0.1-SNAPSHOT" + + // build artifact name as "mill-2.12.4" instead of "mill-2.12" + def useFullScalaVersionForPublish: Boolean = false + + def publishLocal() = T.command { + import publish._ + val file = jar() + val scalaFull = scalaVersion() + val scalaBin = scalaBinaryVersion() + val useFullVersion = useFullScalaVersionForPublish + val deps = ivyDeps() + val dependencies = deps.map(d => Artifact.fromDep(d, scalaFull, scalaBin)) + val artScalaVersion = if (useFullVersion) scalaFull else scalaBin + val artifact = ScalaArtifact(organization(), name(), version(), artScalaVersion) + LocalPublisher.publish(file, artifact, dependencies) + } + } trait SbtScalaModule extends ScalaModule { outer => def basePath: Path diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/publish/IvyFile.scala b/scalaplugin/src/main/scala/mill/scalaplugin/publish/IvyFile.scala new file mode 100644 index 00000000..c9f36ebe --- /dev/null +++ b/scalaplugin/src/main/scala/mill/scalaplugin/publish/IvyFile.scala @@ -0,0 +1,63 @@ +package mill.scalaplugin.publish + +trait IvyFile { + + val head = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + + def generateIvy( + artifact: Artifact, + dependencies: Seq[Dependency], + pomSettings: PomSettings + ): String = { + val xml = ivyXml(artifact, dependencies, pomSettings) + head + xml + } + + // can't use scala-xml + // it escapes '->' inside dependency conf + def ivyXml( + artifact: Artifact, + dependencies: Seq[Dependency], + pomSettings: PomSettings + ): String = { + val deps = dependencies.map(d => { + import d.artifact._ + val scope = scopeToConf(d.scope) + s""" <dependency org="${group}" name="${id}" rev="${version}" conf="${scope}->default(compile)"> + | </dependency> """.stripMargin + }).mkString("\n") + s"""<ivy-module version="2.0" xmlns:e="http://ant.apache.org/ivy/extra"> + | <info organisation="${artifact.group}" module="${artifact.id}" revision="${artifact.version}" + | status="release"> + | <description/> + | </info> + | <configurations> + | <conf name="pom" visibility="public" description=""/> + | <conf extends="runtime" name="test" visibility="public" description=""/> + | <conf name="provided" visibility="public" description=""/> + | <conf name="optional" visibility="public" description=""/> + | <conf name="compile" visibility="public" description=""/> + | <conf extends="compile" name="runtime" visibility="public" description=""/> + | </configurations> + | + | <publications> + | <artifact name="${artifact.id}" type="pom" ext="pom" conf="pom"/> + | <artifact name="${artifact.id}" type="jar" ext="jar" conf="compile"/> + | </publications> + | <dependencies> + |${deps} + | </dependencies> + |</ivy-module> + """.stripMargin + } + + private def scopeToConf(s: Scope): String = s match { + case Scope.Compile => "compile" + case Scope.Provided => "provided" + case Scope.Test => "test" + case Scope.Runtime => "runtime" + } + +} + +object IvyFile extends IvyFile diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/publish/PomFile.scala b/scalaplugin/src/main/scala/mill/scalaplugin/publish/PomFile.scala new file mode 100644 index 00000000..95f05761 --- /dev/null +++ b/scalaplugin/src/main/scala/mill/scalaplugin/publish/PomFile.scala @@ -0,0 +1,90 @@ +package mill.scalaplugin.publish + +import scala.xml.{Elem, NodeSeq} + + +trait PomFile { + + val head = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + + //TODO - not only jar packaging support? + //TODO - description + def generatePom( + artifact: Artifact, + dependencies: Seq[Dependency], + pomSettings: PomSettings + ): String = { + val xml = + <project + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" + xmlns ="http://maven.apache.org/POM/4.0.0"> + + <modelVersion>4.0.0</modelVersion> + <artifactId>{artifact.id}</artifactId> + <packaging>jar</packaging> + <description></description> + + <version>{artifact.version}</version> + <url>{pomSettings.url}</url> + <licenses> + {pomSettings.licenses.map(renderLicense)} + </licenses> + <scm> + <url>{pomSettings.scm.url}</url> + <connection>{pomSettings.scm.connection}</connection> + </scm> + <developers> + {pomSettings.developers.map(renderDeveloper)} + </developers> + <dependencies> + {dependencies.map(renderDependency)} + </dependencies> + </project> + + val pp = new scala.xml.PrettyPrinter(120, 4) + val data = pp.format(xml) + head + data + } + + private def renderLicense(l: License): Elem = { + import l._ + <license> + <name>{name}</name> + <url>{url}</url> + <distribution>{distribution}</distribution> + </license> + } + + private def renderDeveloper(d: Developer): Elem = { + import d._ + <developer> + <id>{id}</id> + <name>{name}</name> + <organization>{organization}</organization> + <organizationUrl>{organizationUrl}</organizationUrl> + </developer> + } + + private def renderDependency(d: Dependency): Elem = { + import d._ + import artifact._ + + val scope = d.scope match { + case Scope.Compile => NodeSeq.Empty + case Scope.Provided => <scope>provided</scope> + case Scope.Test => <scope>test</scope> + case Scope.Runtime => <scope>runtime</scope> + } + <dependency> + <groupId>{group}</groupId> + <artifactId>{id}</artifactId> + <version>{version}</version> + {scope} + </dependency> + } + +} + +object PomFile extends PomFile + diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/publish/Publisher.scala b/scalaplugin/src/main/scala/mill/scalaplugin/publish/Publisher.scala new file mode 100644 index 00000000..99cd13b5 --- /dev/null +++ b/scalaplugin/src/main/scala/mill/scalaplugin/publish/Publisher.scala @@ -0,0 +1,62 @@ +package mill.scalaplugin.publish + +import java.io.File +import java.nio.file.{Files, StandardCopyOption, StandardOpenOption} +import java.security.MessageDigest + +import ammonite.ops._ +import mill.eval.PathRef + +object LocalPublisher { + + val root: Path = { + val ivy2 = { + // a bit touchy on Windows... - don't try to manually write down the URI with s"file://..." + val str = new File(sys.props("user.home") + "/.ivy2/").toString + if (str.endsWith("/")) str else str + "/" + } + Path(ivy2 + "local/") + } + + def publish( + file: PathRef, + artifact: Artifact, + dependencies: Seq[Dependency] + ): String = { + val sett = PomSettings("mill", "url", Seq.empty, SCM("", ""), Seq.empty) + val f = file.path + val pomData = PomFile.generatePom(artifact, dependencies, sett) + val ivyData = IvyFile.generateIvy(artifact, dependencies, sett) + + + val dir = root/artifact.group/artifact.id/artifact.version + + val jars = dir/"jars" + val poms = dir/"poms" + val ivys = dir/"ivys" + + val fileName = artifact match { + case j: JavaArtifact => j.name + case sa: ScalaArtifact => + val postfix = { + val arr = sa.scalaVersion.split('.') + val erased = if (arr.length > 2) arr.dropRight(1) else arr + erased.mkString(".") + } + s"${sa.name}_$postfix" + } + + Seq(dir, jars, poms, ivys).foreach(d => if (!d.toIO.exists()) mkdir(d)) + + Files.copy(f.toNIO, (dir/"jars"/s"$fileName.jar").toNIO, StandardCopyOption.REPLACE_EXISTING) + Files.write((dir/"poms"/s"$fileName.pom").toNIO, pomData.getBytes(), + StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING + ) + Files.write((dir/"ivys"/"ivy.xml").toNIO, ivyData.getBytes(), + StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING + ) + + dir.toString() + } + +} diff --git a/scalaplugin/src/main/scala/mill/scalaplugin/publish/settings.scala b/scalaplugin/src/main/scala/mill/scalaplugin/publish/settings.scala new file mode 100644 index 00000000..ece7fbd1 --- /dev/null +++ b/scalaplugin/src/main/scala/mill/scalaplugin/publish/settings.scala @@ -0,0 +1,90 @@ +package mill.scalaplugin.publish + +import mill.scalaplugin.Dep +import mill.util.JsonFormatters + +trait Artifact extends Serializable with Product { + def group: String + def name: String + def id: String + def version: String +} + +object Artifact { + + def fromDep(dep: Dep, scalaFull: String, scalaBin: String): Dependency = { + dep match { + case d: Dep.Java => + import d.dep._ + val art = JavaArtifact(module.organization, module.name, version) + Dependency(art, Scope.Compile) + case d: Dep.Scala => + import d.dep._ + val art = ScalaArtifact(module.organization, module.name, version, scalaBin) + Dependency(art, Scope.Compile) + case d: Dep.Point => + import d.dep._ + val art = ScalaArtifact(module.organization, module.name, version, scalaFull) + Dependency(art, Scope.Compile) + } + } +} + +case class JavaArtifact( + group: String, + name: String, + version: String +) extends Artifact { + override def id: String = name +} + +case class ScalaArtifact( + group: String, + name: String, + version: String, + scalaVersion: String, +) extends Artifact { + + override def id: String = s"${name}_$scalaVersion" +} + +sealed trait Scope +object Scope { + case object Compile extends Scope + case object Provided extends Scope + case object Runtime extends Scope + case object Test extends Scope +} + +case class Dependency( + artifact: Artifact, + scope: Scope +) + +case class License( + name: String, + url: String, + distribution: String = "repo" +) + +case class SCM( + url: String, + connection: String +) + +case class Developer( + id: String, + name: String, + url: String, + organization: String, + organizationUrl: String +) + +case class PomSettings( + organization: String, + url: String, + licenses: Seq[License], + scm: SCM, + developers: Seq[Developer] +) + diff --git a/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala b/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala index 185cffc8..18f20852 100644 --- a/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala +++ b/scalaplugin/src/test/scala/mill/scalaplugin/AcyclicTests.scala @@ -12,10 +12,9 @@ object AcyclicBuild{ for(crossVersion <- Cross("2.10.6", "2.11.8", "2.12.3", "2.12.4")) yield new SbtScalaModule{outer => def basePath = AcyclicTests.workspacePath - def organization = "com.lihaoyi" - def name = "acyclic" - - def version = "0.1.7" + override def organization = "com.lihaoyi" + override def name = "acyclic" + override def version = "0.1.7" def scalaVersion = crossVersion def ivyDeps = Seq( Dep.Java("org.scala-lang", "scala-compiler", scalaVersion()) |