casualjim
12/18/2010 - 4:12 PM

McPom.scala

//Usage: 
//override def pomPostProcess(node: Node): Node = mcPom(moduleConfigurations)(super.pomPostProcess(node))

trait McPom { self: DefaultProject =>
  import scala.xml._

  def mcPom(mcs: Set[ModuleConfiguration])(node: Node): Node = {
    //make sure we have a trailing slash so we deduplicate URLs properly
    def cleanUrl(url: String) = url match {
      case null => ""
      case "" => ""
      case u if u endsWith "/" => u
      case u => u + "/"
    }
    //Parse out the old repos so we can deduplicate
    val oldRepos = (node \\ "project" \ "repositories" \ "repository").
                     map( n => cleanUrl((n \ "url").text) -> (n \ "name").text).toList
    //Get our MavenRepositories from our MCs
    val newRepos = mcs.filter(_.resolver.isInstanceOf[MavenRepository]).map(m => {
                      val r = m.resolver.asInstanceOf[MavenRepository]
                      cleanUrl(r.root) -> r.name
                   })
    //Create the XML, goes via Map to ensure that we don't have duplicate URLs
    val repos = Map((oldRepos ++ newRepos):_*).map( pair =>
                  <repository>
                     <id>{pair._2.toSeq.filter(_.isLetterOrDigit).mkString}</id>
                     <name>{pair._2}</name>
                     <url>{pair._1}</url>
                  </repository>
                )
    //a recursive tree rewriter for our XML
    def rewrite(pf:PartialFunction[Node,Node])(ns: Seq[Node]): Seq[Node] = for(subnode <- ns) yield subnode match {
        case e: Elem =>
          if (pf isDefinedAt e) pf(e)
          else Elem(e.prefix, e.label, e.attributes, e.scope, rewrite(pf)(e.child):_*)
        case other => other
    }
    //If there are no repos in the pom - create entry, or else add to existing
    val rule: PartialFunction[Node,Node] = if ((node \\ "project" \ "repositories" ).isEmpty) {
      case Elem(prefix, "project", attribs, scope, children @ _*) =>
           Elem(prefix, "project", attribs, scope, children ++ <repositories>{repos}</repositories>:_*)
    } else {
      case Elem(prefix, "repositories", attribs, scope, children @ _*) =>
           Elem(prefix, "repositories", attribs, scope, repos.toList:_*)
    }
    //Work that magic!
    rewrite(rule)(node.theSeq)(0)
  }
}