Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
arturaz committed Sep 24, 2024
1 parent 92a7211 commit 3bcf834
Show file tree
Hide file tree
Showing 13 changed files with 748 additions and 8 deletions.
27 changes: 19 additions & 8 deletions main/src/mill/main/MainModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,9 @@ trait MainModule extends BaseModule0 {
/**
* Shuts down mill's background server
*/
def shutdown(): Command[Unit] = Target.command {
def shutdown(): Command[Unit] = Task.Command {
Target.log.info("Shutting down Mill server...")
Target.ctx.systemExit(0)
Target.ctx().systemExit(0)
()
}

Expand All @@ -400,12 +400,23 @@ trait MainModule extends BaseModule0 {
* You can use it to quickly generate a starter project. There are lots of
* templates out there for many frameworks and tools!
*/
def init(evaluator: Evaluator, args: String*): Command[Unit] = Target.command {
RunScript.evaluateTasksNamed(
evaluator,
Seq("mill.scalalib.giter8.Giter8Module/init") ++ args,
SelectMode.Separated
)
def init(evaluator: Evaluator, args: String*): Command[Unit] = Task.Command {
Task.log.info("Looking up whether this is a Maven project that we could convert into Mill...")
val rootPom = Task.workspace / "pom.xml"

if (os.exists(rootPom)) {
Task.log.info(s"Detected a Maven project at $rootPom, converting to Mill...")
initializers.MavenInit(Task.workspace, rootPom, Task.log, evaluator, args: _*)
}
else {
Task.log.info("Not a Maven project ('pom.xml' not found). Generating a Giter8 project instead...")

RunScript.evaluateTasksNamed(
evaluator,
Seq("mill.scalalib.giter8.Giter8Module/init") ++ args,
SelectMode.Separated
)
}

()
}
Expand Down
16 changes: 16 additions & 0 deletions main/src/mill/main/initializers/MavenInit.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package mill.main.initializers

import mill.api.Logger
import mill.eval.Evaluator
import os.Path

object MavenInit {
def apply(workspace: Path, rootPom: Path, log: Logger, evaluator: Evaluator, args: String*): Unit = {
maven.JavaModule.readFrom(rootPom) match {
case Left(error) => log.error(error)
case Right(module) =>
log.info(module.render)
os.write(workspace / "build.mill", module.render)
}
}
}
47 changes: 47 additions & 0 deletions main/src/mill/main/initializers/maven/Dependency.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package mill.main.initializers.maven

import scala.xml.Node

/** Dependency for `dependencies` section of POM. */
private[maven] case class Dependency(
groupId: TemplatedString, artifactId: TemplatedString, version: Option[TemplatedString],
type_ : Option[DependencyType], scope: DependencyScope
) {
override def toString: String =
s"Dependency(groupId=$groupId, artifactId=$artifactId, version=$version, type=$type_, scope=$scope)"

def asDependencyManagement(properties: PropertyMap): Either[String, String] = {
for {
groupId <- groupId.resolve(properties).left.map(err => s"Could not resolve groupId for $this: $err")
artifactId <- artifactId.resolve(properties).left.map(err => s"Could not resolve artifactId for $this: $err")
} yield s"$groupId:$artifactId"
}

def render(properties: PropertyMap): String = {
val versionStr = version match {
case Some(version) => version.renderForInsideString(TemplatedString.ScopeName.Properties)
case None =>
TemplatedString(s"$${${asDependencyManagement(properties)}")
.renderForInsideString(TemplatedString.ScopeName.DependencyManagement)
}

val str = s"${groupId.renderForInsideString(TemplatedString.ScopeName.Properties)}:${
artifactId.renderForInsideString(TemplatedString.ScopeName.Properties)}:$versionStr"
s"ivy${str.renderAsString}"
}
}
private[maven] object Dependency {
def parse(xml: Node): Either[String, Dependency] = {
for {
groupId <- readSingleText(xml, "groupId").map(TemplatedString.apply)
artifactId <- readSingleText(xml, "artifactId").map(TemplatedString.apply)
version <- readMaybeSingleText(xml, "version").map(_.map(TemplatedString.apply))
type_ <- readMaybeSingleText(xml, "type").map(_.map(DependencyType.parse))
scope <- readMaybeSingleText(xml, "scope").flatMap { opt =>
opt
.map(DependencyScope.parse(_).left.map(err => s"$err for $xml"))
.getOrElse(Right(DependencyScope.Compile))
}
} yield apply(groupId = groupId, artifactId = artifactId, version = version, type_ = type_, scope = scope)
}
}
42 changes: 42 additions & 0 deletions main/src/mill/main/initializers/maven/DependencyScope.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package mill.main.initializers.maven

/** https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#dependency-scope */
private[maven] sealed trait DependencyScope {
def render: String = this match {
case DependencyScope.Compile => "compile"
case DependencyScope.Provided => "provided"
case DependencyScope.Runtime => "runtime"
case DependencyScope.Test => "test"
case DependencyScope.System => "system"
case DependencyScope.Import => "import"
}
}
private[maven] object DependencyScope {
case object Compile extends DependencyScope

/** This is much like compile, but indicates you expect the JDK or a container to provide the dependency at
* runtime. */
case object Provided extends DependencyScope

/** This scope indicates that the dependency is not required for compilation, but is for execution. Maven includes
* a dependency with this scope in the runtime and test classpaths, but not the compile classpath. */
case object Runtime extends DependencyScope

case object Test extends DependencyScope

/** This scope is similar to provided except that you have to provide the JAR which contains it explicitly.
* The artifact is always available and is not looked up in a repository. */
case object System extends DependencyScope

case object Import extends DependencyScope

def parse(str: String): Either[String, DependencyScope] = str match {
case "compile" => Right(Compile)
case "provided" => Right(Provided)
case "runtime" => Right(Runtime)
case "test" => Right(Test)
case "system" => Right(System)
case "import" => Right(Import)
case _ => Left(s"Unknown dependency scope: '$str'")
}
}
12 changes: 12 additions & 0 deletions main/src/mill/main/initializers/maven/DependencyType.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package mill.main.initializers.maven

private[maven] sealed trait DependencyType
private[maven] object DependencyType {
case object POM extends DependencyType
case class Other(value: String) extends DependencyType

def parse(str: String): DependencyType = str match {
case "pom" => POM
case _ => Other(str)
}
}
Loading

0 comments on commit 3bcf834

Please sign in to comment.