summaryrefslogtreecommitdiff
path: root/scalalib/src/publish/Pom.scala
blob: a7f1f6fca8bcfb2e69c798c34aa8ce9821ce3f60 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package mill.scalalib.publish

import mill.api.Loose.Agg

import scala.xml.{Atom, Elem, NodeSeq, PrettyPrinter}

object Pom {

  val head = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"

  implicit class XmlOps(val e: Elem) extends AnyVal {
    // source: https://stackoverflow.com/a/5254068/449071
    def optional : NodeSeq = {
      require(e.child.length == 1)
      e.child.head match {
        case atom: Atom[Option[_]] => atom.data match {
          case None    => NodeSeq.Empty
          case Some(x) => e.copy(child = x match {
            case n: NodeSeq => n
            case x => new Atom(x)
          })
        }
        case _ => e
      }
    }
  }

  //TODO - not only jar packaging support?
  def apply(artifact: Artifact,
            dependencies: Agg[Dependency],
            name: String,
            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>
        <name>{name}</name>
        <groupId>{artifact.group}</groupId>
        <artifactId>{artifact.id}</artifactId>
        <packaging>jar</packaging>
        <description>{pomSettings.description}</description>

        <version>{artifact.version}</version>
        <url>{pomSettings.url}</url>
        <licenses>
          {pomSettings.licenses.map(renderLicense)}
        </licenses>
        <scm>
          { <connection>{pomSettings.versionControl.connection}</connection>.optional }
          { <developerConnection>{pomSettings.versionControl.developerConnection}</developerConnection>.optional }
          { <tag>{pomSettings.versionControl.tag}</tag>.optional }
          { <url>{pomSettings.versionControl.browsableRepository}</url>.optional }
        </scm>
        <developers>
          {pomSettings.developers.map(renderDeveloper)}
        </developers>
        <dependencies>
          {dependencies.map(renderDependency).toSeq}
        </dependencies>
      </project>

    val pp = new PrettyPrinter(120, 4)
    head + pp.format(xml)
  }

  private def renderLicense(l: License): Elem = {
    <license>
      <name>{l.name}</name>
      <url>{l.url}</url>
      <distribution>{l.distribution}</distribution>
    </license>
  }

  private def renderDeveloper(d: Developer): Elem = {
    <developer>
      <id>{d.id}</id>
      <name>{d.name}</name>
      { <organization>{d.organization}</organization>.optional }
      { <organizationUrl>{d.organizationUrl}</organizationUrl>.optional }
    </developer>
  }

  private def renderDependency(d: Dependency): Elem = {
    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>
    }
    if (d.exclusions.isEmpty)
      <dependency>
        <groupId>{d.artifact.group}</groupId>
        <artifactId>{d.artifact.id}</artifactId>
        <version>{d.artifact.version}</version>
        {scope}
      </dependency>
    else
      <dependency>
        <groupId>{d.artifact.group}</groupId>
        <artifactId>{d.artifact.id}</artifactId>
        <version>{d.artifact.version}</version>
        <exclusions>
          {d.exclusions.map(ex =>
            <exclusion>
              <groupId>{ex._1}</groupId>
              <artifactId>{ex._2}</artifactId>
            </exclusion>
          )}
        </exclusions>
        {scope}
      </dependency>
  }

}