<?xml version="1.0"?>
<!-- 
/*
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 -->


<project
  xmlns:ant="jelly:ant"
  xmlns:archive="release:archive"
  xmlns:transform="release:transform"
  xmlns:define="jelly:define"
  xmlns:deploy="deploy"
  xmlns:maven="jelly:maven"
  xmlns:j="jelly:core"
  xmlns:i="jelly:interaction"
  xmlns:u="jelly:util"
  xmlns:r="jelly:org.apache.maven.release.jelly.ReleaseTagLibrary">

  <!-- ================================================================== -->
  <!-- R E L E A S E  T A G  L I B R A R Y                                -->
  <!-- ================================================================== -->

  <!--
   | Process for a release:
   |
   | o tagging cvs
   | o change the version displayed when Maven is run
   | o building source distribution
   | o building binary distribution
   | o notifying lists - we need a mailtag that can deal with authorization.
   |   my smtp for example will not let me poke it without a password.
   | o pushing out RSS feeds maybe to javablogs?
   | o updating the <version/> element in the POM
   | o updating changes document
   | o updating the status page
   | o flipping the site from HEAD to release and deploy the site
   | o all SNAPSHOT references must be changed to timestamped versions
   | o incrementing the version - what rules do we want to follow? they
   |   have to be documented so we need a document to adhere to.
   | o Deploying the POM for the released version so there is always history on
   |   what went into a specific version. Eventually it would also be nice to
   |   trace back through the POMs so you could build any version of any
   |   project from sources at any point in time.
   | Q: so how do we find the latest timestamped version.
   | A: when a snapshot is deployed we need a file with the real version
   |    of the latest snapshot.
   -->

    <!--
    | Archive taglib:
    |	- copy-dependencies: copies dependencies for category groups
    |            attributes: category, todir
    |   - gzip: creates tar.gz distribution file
    |            attributes: dir, name
    |   - zip: creates zip distribution file 	
    |            attributes: dir, name
    -->	
    <define:taglib uri="release:archive">
        <define:tag name="copy-dependencies">
            <j:if test="${projectDescriptor != null}">
                <maven:pom var="pom" projectDescriptor="${projectDescriptor}"/>
            </j:if>

            <j:set var="mavenRepoLocal" value='${context.getVariable("maven.repo.local")}'/>
            <j:forEach var="dependency" items="${pom.dependencies}">
                <j:if test='${category.equals(dependency.getProperty("category"))}'>
                    <j:set var="addDependencies" value='true'/>
                </j:if>
            </j:forEach>

            <j:if test='${addDependencies == "true" }'>
                <ant:mkdir dir="${todir}"/>
                <ant:copy todir="${todir}" flatten="true">
                    <ant:fileset dir="${mavenRepoLocal}">
                        <j:forEach var="dependency" items="${pom.dependencies}">
                            <j:if test='${category.equals(dependency.getProperty("category"))}'>
                                <ant:include name="${dependency.artifactDirectory}/jars/${dependency.artifact}"/>
                                <ant:include name="${dependency.artifactDirectory}/licenses/${dependency.artifactId}.license"/>
                            </j:if>
                        </j:forEach>
                    </ant:fileset>
                </ant:copy>
            </j:if>
        </define:tag>
        <define:tag name="gzip">
	    <ant:tar longfile="gnu" tarfile="${maven.build.dir}/${name}.tar">
                <ant:tarfileset dir="${dir}" prefix="${name}"/>
            </ant:tar>
    	    <ant:gzip zipfile="${maven.build.dir}/${name}.tar.gz"
                        src="${maven.build.dir}/${name}.tar"/>
            <ant:delete file="${maven.build.dir}/${name}.tar"/>
        </define:tag>
        <define:tag name="zip">
            <ant:zip destfile="${maven.build.dir}/${name}.zip">
                <ant:zipfileset dir="${dir}" prefix="${name}"/>
    	    </ant:zip>
        </define:tag>
        <define:tag name="deploy">
	    <deploy:artifact
        	  artifact="${maven.build.dir}/${name}"
       		  type="distributions"
	          assureDirectoryCommand="mkdir -p"
	      	  siteCommand="cd @deployDirectory@; chmod g+w ${name}; chgrp ${maven.remote.group} ${name}"/>
        </define:tag>
    </define:taglib>

    <define:taglib uri="release:transform">
      <define:tag name="release-version">
        <r:release-version
          version="${version}"
          tag="${tag}"
          transformer="transformer"
          transformations="transformations"/>
        <j:set var="required" value="${transformer.transformRequired()}" />
        <j:if test="${required}">
          <ant:echo>Updating POM with version ${version}; tag ${tag}</ant:echo>
          ${transformer.transformNodes()}
          ${transformer.write()}
        </j:if>
      </define:tag>
    </define:taglib>

  <goal name="release:update-pom">
    <transform:release-version
      version="${version}"
      tag="${tag}" />
  </goal>

  <!--
   |
   | Convert SNAPSHOT version identifiers to real snapshot versions.
   | You cannot leave SNAPSHOT version identifiers in the POM for a
   | release.
   |
   -->
  <goal name="convert-snapshots">

    <r:resolve-snapshots
      transformer="transformer"
      transformations="transformations"/>

    <i:ask
      question="There are ${transformer.selectedNodeCount} snapshot dependencies, would you like to update them to use timestamped versions?"
      answer="answer"
      default="yes"/>

    <j:if test="${answer == 'yes'}">

      <j:forEach var="transformation" items="${transformations}">

        <!-- Display transformation info. Needs to be consumable by a GUI. -->
        
        <j:expr value="${transformation.beforeTransformation}"/>
        <echo/>
        <j:expr value="${transformation.afterTransformation}"/>
        <echo/>

        <i:ask
          question="Do you want to update this dependency?"
          answer="answer"
          default="yes"/>

        <j:if test="${answer == 'yes'}">

          <!-- Change the node. -->
          ${transformation.transform()}"/>

        </j:if>

      </j:forEach>

      <i:ask
        question="Would you like the update POM to be written out for the release?"
        answer="answer"
        default="yes"/>

      <j:if test="${answer == 'yes'}">
        <!-- Write out the pom. -->
        ${transformer.write()}
      </j:if>

    </j:if>
  </goal>

  <goal name="convert-snapshots-auto">

    <r:resolve-snapshots
      transformer="transformer"
      transformations="transformations"/>

      ${transformer.transformNodes()}
      ${transformer.write()}

  </goal>

  <goal name="increment-snapshot-version">
    <r:increment-snapshot-version
      transformer="transformer"
      transformations="transformations"/>
      ${transformer.transformNodes()}
      ${transformer.write()}
  </goal>

  <!--
   |
   | Validate the POM for a release. This consists of:
   |
   | 1) Making sure all SNAPSHOT version identifiers are converted.
   |
   -->
  <goal name="validate-pom-for-release">

    <j:useBean var="snapshots" class="java.util.ArrayList"/>

    <j:forEach var="dependency" items="${pom.dependencies}">
      <j:if test="${dependency.version == 'SNAPSHOT'}">
        <j:set var="dummy" value="${snapshots.add(dependency)}"/>
      </j:if>
    </j:forEach>

    <j:if test="${size(snapshots) > 0}">
      <echo/>
      <echo>The following dependencies have SNAPSHOT identifiers:</echo>
      <echo/>
      <j:forEach var="dependency" items="${snapshots}">
        <echo>${dependency.artifactId}</echo>
      </j:forEach>
      <fail message="">
      </fail>
    </j:if>

  </goal>

  <!--
   |
   | Release
   |
   -->
  <goal name="release">

    <attainGoal name="validate-pom-for-release"/>
    <attainGoal name="deploy:pom"/>

    <!--
     |
     | Build the binary and source distributions. We need to alter
     | the process so that we can build everything to check and then
     | deploy instead of having to build everything all the time.
     |
     -->
  </goal>

  <!--
   |
   | Initialise release variables
   |
   -->
  <goal name="release:init">
    <j:set var="releaseNameBin" value="${maven.release.name.bin}"/>
    <j:if test="${empty(releaseNameBin)}">
      <j:set var="releaseNameBin" value="${pom.artifactId}-${pom.currentVersion}-bin"/>
    </j:if>
    <j:set var="releaseNameSrc" value="${maven.release.name.src}"/>
    <j:if test="${empty(releaseNameSrc)}">
      <j:set var="releaseNameSrc" value="${pom.artifactId}-${pom.currentVersion}-src"/>
    </j:if>
  </goal>
 
 <!--
   |
   | Build a binary distribution copying dependencies according to 
   | category groups.
   |
   -->
  <goal name="release:setup-distribution-bin" prereqs="release:init">
    <ant:mkdir dir="${maven.build.dir}/${releaseNameBin}"/>
    <u:tokenize var="categories" delim="," trim="true">${maven.release.distribution.categories}</u:tokenize>
    <j:forEach var="category" items="${categories}">
 	<u:tokenize var="pair" delim=":" trim="true">${category}</u:tokenize>
  	<j:set var="name" value="${pair.get(0)}"/>
  	<j:set var="path" value="${pair.get(1)}"/>
 	<archive:copy-dependencies category="${name}" todir="${maven.build.dir}/${releaseNameBin}/${path}"/>
    </j:forEach> 
  </goal>

  <goal name="release:build-distribution-bin" prereqs="release:setup-distribution-bin">
    <archive:gzip name="${releaseNameBin}" dir="${maven.build.dir}/${releaseNameBin}"/>
    <archive:zip name="${releaseNameBin}" dir="${maven.build.dir}/${releaseNameBin}"/>
  </goal>

  <!--
   |
   | Build a source distribution from source repository.
   | Uses scm plugin to checkout project.
   |
   -->
  <goal name="release:build-distribution-src" prereqs="release:init,scm:checkout-project">
    <archive:gzip name="${releaseNameSrc}" dir="${maven.scm.checkout.dir}/${maven.scm.cvs.module}"/>
    <archive:zip name="${releaseNameSrc}" dir="${maven.scm.checkout.dir}/${maven.scm.cvs.module}"/>
  </goal>

 <!--
   |
   | Deploy a binary distribution.
   |
   -->
  <goal name="release:deploy-distribution-bin" prereqs="release:build-distribution-bin">
    <archive:deploy name="${releaseNameBin}.tar.gz"/>
    <archive:deploy name="${releaseNameBin}.zip"/>
  </goal>

 <!--
   |
   | Deploy a source distribution.
   |
   -->
  <goal name="release:deploy-distribution-src" prereqs="release:build-distribution-src">
    <archive:deploy name="${releaseNameSrc}.tar.gz"/>
    <archive:deploy name="${releaseNameSrc}.zip"/>
  </goal>

</project>
