/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Ant", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* .
*/
package org.apache.tools.ant.taskdefs.cvslib;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Cvs;
import org.apache.tools.ant.taskdefs.Delete;
import org.apache.tools.ant.taskdefs.Move;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.util.FileUtils;
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
/**
* Exports all the files in a module which have been changed between two tags.
*
* @author Andrew Liles
* @version $Revision: 1.2 $ $Date: 2002/10/07 16:49:10 $
* @since Ant 1.6??
* @ant.task name="cvsexportdiff"
*/
public class CvsExportDiff extends Task {
/**
* The task used to effect the diff
*/
protected CvsTagDiff cvsTagDiffTask;
/**
* The task used to effect the export
*/
protected Cvs cvsExportTask;
/**
* The destination directory files should be exported into
*/
protected File dest;
/**
* The destination directory files should be exported into
*/
protected File workingDirectory;
protected String exportPackage;
protected List defaultArguments = new Vector();
/**
* Set the destination directory into which the identified files should be exported to
* @see CvsExportDiff#setWorkingDirectory()
*/
public void setDest(File dest) {
this.dest = dest;
}
/**
* This method returns the destination directory for the export
* @see CvsExportDiff#getWorkingDirectory()
*/
public File getDest() {
return this.dest;
}
/**
* This method defines the working directory for the temporary checkout
* This is mandatory.
* @param dest - the working directory
* @see CvsExportDiff#setDest()
*/
public void setWorkingDirectory(File workingDirectory) {
this.workingDirectory = workingDirectory;
}
/**
* This method returns the destination directory for the export
* @see CvsExportDiff#getWorkingDirectory()
*/
public File getWorkingDirectory() {
return workingDirectory;
}
/**
* Initialize this task.
* This task initializes a member cvs task and a member of CvsTagDiff
* in init() to perform the diff and export in execute().
*
* @exception BuildException if an error occurs
*/
public void init() throws BuildException {
cvsTagDiffTask = (CvsTagDiff) getProject().createTask("cvstagdiff");
cvsTagDiffTask.init();
cvsExportTask = (Cvs) getProject().createTask("cvs");
cvsExportTask.init();
}
/**
* Use this add a custom argument to the command line, see Cvs Task documentation
*/
public void addCommandArgument(String arg) {
defaultArguments.add(arg);
}
/**
* If set to a value 1-9 it adds -zN to the cvs command line, else
* it disables compression.
*
* @see org.apache.tools.ant.taskdefs.AbstractCvsTask#setCompressionLevel(int)
*/
public void setCompressionLevel(int level) {
cvsTagDiffTask.setCompressionLevel(level);
cvsExportTask.setCompressionLevel(level);
}
/**
* If true, this is the same as compressionlevel="3".
*/
public void setCompression(boolean usecomp) {
cvsTagDiffTask.setCompression(usecomp);
cvsExportTask.setCompression(usecomp);
}
/**
* The CVSROOT variable.
*/
public void setCvsRoot(String cvsRoot) {
cvsTagDiffTask.setCvsRoot(cvsRoot);
cvsExportTask.setCvsRoot(cvsRoot);
}
/**
* The CVS_RSH variable.
*/
public void setCvsRsh(String rsh) {
cvsTagDiffTask.setCvsRsh(rsh);
cvsExportTask.setCvsRsh(rsh);
}
/**
* Stop the build process if the command exits with
* a return code other than 0.
* Defaults to false.
*/
public void setFailOnError(boolean b) {
cvsTagDiffTask.setFailOnError(b);
cvsExportTask.setFailOnError(b);
}
/**
* The package/module to analyze.
*/
public void setPackage(String p) {
cvsTagDiffTask.setPackage(p);
this.exportPackage = p;
}
/**
* Password file to read passwords from.
*/
public void setPassfile(File f) {
cvsTagDiffTask.setPassfile(f);
cvsExportTask.setPassfile(f);
}
/**
* Port used by CVS to communicate with the server.
*/
public void setPort(int port) {
cvsTagDiffTask.setPort(port);
cvsExportTask.setPort(port);
}
/**
* If true, suppress informational messages.
*/
public void setQuiet(boolean quiet) {
cvsTagDiffTask.setQuiet(quiet);
cvsExportTask.setQuiet(quiet);
}
/**
* Set the start tag.
*
* @param s the start tag.
*/
public void setStartTag(String s) {
cvsTagDiffTask.setStartTag(s);
}
/**
* Set the start date.
*
* @param s the start date.
*/
public void setStartDate(String s) {
cvsTagDiffTask.setStartDate(s);
}
/**
* Set the end tag.
*
* @param s the end tag.
*/
public void setEndTag(String s) {
cvsTagDiffTask.setEndTag(s);
}
/**
* Set the end date.
*
* @param s the end date.
*/
public void setEndDate(String s) {
cvsTagDiffTask.setEndDate(s);
}
/**
* Validate the parameters specified for task.
*
* @exception BuildException if a parameter is not correctly set
*/
protected void validate() throws BuildException {
if (getWorkingDirectory()==null) {
throw new BuildException("Working directory (workingDirectory) must be set");
}
if (dest==null) {
throw new BuildException("Destination directory (dest) must be set");
}
}
/**
* Execute task.
*
* @exception BuildException if an error occurs
*/
public void execute() throws BuildException {
log("Starting CvsExportDiff");
// validate the input parameters
validate();
if((cvsTagDiffTask==null) || (cvsExportTask==null))
throw new BuildException("Initialisation failed to create embedded CvsTagDiff or Cvs tasks");
try {
CvsTagEntry[] entries = generateCvsTagEntries(cvsTagDiffTask);
int exportFileCount = 0;
for(int entryIndex=0; entryIndex0) {
//cleanup working directory before we start (CVS export task will re-make this directory)
Delete deleteTask = (Delete) getProject().createTask("delete");
deleteTask.setDir(getWorkingDirectory());
deleteTask.setQuiet(true);
deleteTask.execute();
//we want the CVS task to work in multiple Command line mode, so ensure that the singleton command is not set
cvsExportTask.setCommand(null);
cvsExportTask.setDest(getWorkingDirectory());
cvsExportTask.setFailOnError(true);
for(int entryIndex=0; entryIndex
* Target CVS command:
* cvs -d :pserver:someone@127.0.0.1:/project1 checkout -r1.4 -l module1/module1.2/module1.2.6/file.txt
* @param exportPackage - a package to export (ie. module prefix)
* @param module - an object identifying the file and version to be exported
* @param defaultArguments - a set of String arguments to be added to the command (can be null)
**/
public static Commandline createExportCommandline(String exportPackage, CvsTagEntry module, List defaultArguments)
{
Commandline cl = new Commandline();
if(defaultArguments!=null)
for(Iterator it=defaultArguments.iterator(); it.hasNext(); )
cl.createArgument().setValue((String) it.next());
cl.createArgument().setValue("checkout");
cl.createArgument().setValue("-r" + module.getRevision());
cl.createArgument().setValue("-l");
cl.createArgument().setLine(exportPackage+"/"+module.getFile());
return cl;
}
/**
* Perform the Diff function to determine the set of files
* @todo - perhaps this could be modified to take the data direct from the CvsTagDiff class
* @param - the configured CVSTagDiff task
**/
public static CvsTagEntry[] generateCvsTagEntries (CvsTagDiff cvsTagDiffTask) throws BuildException {
try {
File tagDiff;
try {
tagDiff = File.createTempFile("tagdiff", ".xml");
tagDiff.deleteOnExit();
}
catch (IOException ioe) {
throw new BuildException("Could not create temporary file; check JVM has a temporary directory defined");
}
cvsTagDiffTask.setDestFile(tagDiff);
cvsTagDiffTask.execute();
CvsTagEntry[] entries = parseXML(tagDiff);
tagDiff.delete();
return entries;
}
catch (BuildException be) {
throw be;
}
catch (Exception e) {
throw new BuildException("Failed to obtain diff entries; embedded Exception: " + e, e);
}
}
/**
* Parses the TagDiff XML file.
* @param the file to parse.
*/
protected static CvsTagEntry[] parseXML(File tagDiff) throws IOException, SAXException, ParserConfigurationException, BuildException {
/** Expected format:
Library/as/asset/casestudy.html
1.2
1.1
Library/contactInfo/startup-main.html
1.1
**/
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(tagDiff);
NodeList entryNodes = doc.getElementsByTagName("entry");
CvsTagEntry[] entries = new CvsTagEntry[entryNodes.getLength()];
for(int entryIndex=0; entryIndex element is meant to be the first and only child of the element
NodeList fileNodes = ((Element) entry).getElementsByTagName("file");
file = (Element) fileNodes.item(0);
}
catch (ClassCastException cce) {
throw new BuildException("XML file in unexpected format", cce);
}
NodeList nameNodes = file.getElementsByTagName("name");
String fileName = nameNodes.item(0).getFirstChild().getNodeValue();
NodeList revisionNodes = file.getElementsByTagName("revision");
String revision = null;
if(revisionNodes.getLength()>0)
revision = revisionNodes.item(0).getFirstChild().getNodeValue();
NodeList prerevisionNodes = file.getElementsByTagName("prerevision");
String prerevision = null;
if(prerevisionNodes.getLength()>0)
prerevision = prerevisionNodes.item(0).getFirstChild().getNodeValue();
entries[entryIndex] = new CvsTagEntry(fileName, revision, prerevision);
}
return entries;
}
}