From 784f04c929eb440b8c3b792671053f789160da4f Mon Sep 17 00:00:00 2001 From: Peter Donald Date: Mon, 15 Apr 2002 09:53:24 +0000 Subject: [PATCH] org.apache.tools.ant.taskdefs.cvslib.CvsTagDiff The goal of this task is to give a list of differences between two tags or dates. It produces an xml report like the changelog report of the CvsChangeLog task. The output gives the list of modified files, removed files and new files. The proposed task name is cvstagdiff. PR: 8086 Submitted by: fred@castify.net (Frederic Lavigne) git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272429 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 1 + docs/manual/CoreTasks/cvstagdiff.html | 159 ++++++ docs/manual/coretasklist.html | 1 + docs/manual/tasksoverview.html | 7 + src/etc/tagdiff.xsl | 162 ++++++ .../tools/ant/taskdefs/cvslib/CvsTagDiff.java | 535 ++++++++++++++++++ 6 files changed, 865 insertions(+) create mode 100644 docs/manual/CoreTasks/cvstagdiff.html create mode 100644 src/etc/tagdiff.xsl create mode 100644 src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagDiff.java diff --git a/build.xml b/build.xml index 3d1d8ceb9..c2aea9068 100644 --- a/build.xml +++ b/build.xml @@ -790,6 +790,7 @@ + diff --git a/docs/manual/CoreTasks/cvstagdiff.html b/docs/manual/CoreTasks/cvstagdiff.html new file mode 100644 index 000000000..795b776e6 --- /dev/null +++ b/docs/manual/CoreTasks/cvstagdiff.html @@ -0,0 +1,159 @@ + + + + +CvsTagDiff Task + + + + +

CvsTagDiff

+

Description

+

Generates an XML-formatted report file of the changes between two tags or dates recorded in a +CVS repository.

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
startTagThe earliest tag from which diffs are to be + included in the report.exactly one of the two.
startDateThe earliest date from which diffs are to be + included in the report.
endTagThe latest tag from which diffs are to be + included in the report.exactly one of the two.
endDateThe latest date from which diffs are to be + included in the report.
destfileThe file in which to write the diff report.Yes
+ +

Parameters inherited from the cvs task

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
compressiontrue, false, or the number 1-9 (corresponding to possible values for CVS -z# argument). Any other value is treated as falseNo. Defaults to no compression. if passed true, level 3 compression is assumed.
cvsRootthe CVSROOT variable.No
cvsRshthe CVS_RSH variable.No
packagethe package/module to analyze.Yes
quietsuppress informational messages.No, default "false"
portPort used by CVS to communicate with the server.No, default port 2401.
passfilePassword file to read passwords from.No, default file ~/.cvspass.
failonerrorStop the buildprocess if the command exits with a + returncode other than 0. Defaults to falseNo
+ +

Examples

+
  <cvstagdiff cvsRoot=":pserver:anoncvs@cvs.apache.org:/home/cvspublic"
+                destfile="tagdiff.xml"
+                package="jakarta-ant"
+                startTag="ANT_14"
+                endTag="ANT_141"
+  />
+ +

Generates a tagdiff report for all the changes that have been made +in the jakarta-ant module between the tags ANT_14 and ANT_141. +It writes these changes into the file tagdiff.xml.

+ +
  <cvstagdiff
+                destfile="tagdiff.xml"
+                package="jakarta-ant"
+                startDate="2002-01-01"
+                endDate="2002-31-01"
+  />
+ +

Generates a tagdiff report for all the changes that have been made +in the jakarta-ant module in january 2002. In this example cvsRoot +has not been set. The current cvsRoot will be used (assuming the build is started +from a folder stored in cvs. +It writes these changes into the file tagdiff.xml.

+ +

Generate Report

+

Ant includes a basic XSLT stylesheet that you can use to generate +a HTML report based on the xml output. The following example illustrates +how to generate a HTML report from the XML report.

+ +
+        <style in="tagdiff.xml" 
+               out="tagdiff.html" 
+               style="${ant.home}/etc/tagdiff.xsl">
+          <param name="title" expression="Ant Diff"/>
+          <param name="module" expression="jakarta-ant"/>
+          <param name="cvsweb" expression="http://cvs.apache.org/viewcvs/"/>
+        </style>
+
+ +

Sample Output

+
+<?xml version="1.0" encoding="UTF-8"?>
+<tagdiff startTag="ANT_14" endTag="ANT_141">
+  <entry>
+    <file>
+      <name>src/main/org/apache/tools/ant/DirectoryScanner.java</name>
+      <revision>1.15.2.1</revision>
+      <prevrevision>1.15</prevrevision>
+    </file>
+  </entry>
+</tagdiff>
+
+ +

Copyright © 2002 Apache Software Foundation. All rights +Reserved.

+ + + + diff --git a/docs/manual/coretasklist.html b/docs/manual/coretasklist.html index a309f92b0..fa7a63f38 100644 --- a/docs/manual/coretasklist.html +++ b/docs/manual/coretasklist.html @@ -33,6 +33,7 @@ Cvs
CvsChangeLog
CVSPass
+CvsTagDiff
Delete
Deltree
Dependset
diff --git a/docs/manual/tasksoverview.html b/docs/manual/tasksoverview.html index 59837af98..0ee562b7f 100644 --- a/docs/manual/tasksoverview.html +++ b/docs/manual/tasksoverview.html @@ -959,6 +959,13 @@ documentation.

has the same affect as a cvs login command.

+ + CvsTagDiff +

Generates an XML-formatted report file of the changes between + two tags or dates recorded in a CVS repository.

+ + ClearCase

Tasks to perform the ClearCase cccheckin, cccheckout, diff --git a/src/etc/tagdiff.xsl b/src/etc/tagdiff.xsl new file mode 100644 index 000000000..4dac8f4b7 --- /dev/null +++ b/src/etc/tagdiff.xsl @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + <xsl:value-of select="$title"/> + + + +

+ +

+ Tagdiff between and + +

Designed for use with Ant.

+
+ + + + + +
+ New Files | + Modified Files | + Removed Files +
+ + + New Files + New + + + + + Modified Files + Modified + + + + + Removed Files + Removed + + +
+ + + + + + + + + + + +
+ + - entries + + (back to top) + + + + + + + +
    + +
+ + + + + + + + + + + + + + + + + + + + mailto: + + + + + + +
  • + + / + + + + + + + + /?rev=&content-type=text/x-cvsweb-markup + + + /?r1=&r2=&diff_format=h + + () + + +
  • +
    + + + + + + + diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagDiff.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagDiff.java new file mode 100644 index 000000000..a8c482d0e --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsTagDiff.java @@ -0,0 +1,535 @@ +/* + * 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.util.FileUtils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.Enumeration; +import java.util.Vector; + +/** + * Cvs tag diff. + * The task will examine the output of cvs rdiff between two tags. + * It produces an XML output representing the list of changes. + *
    + * <!-- Root element -->
    + * <!ELEMENT tagdiff ( entry+ ) >
    + * <!-- Start tag of the report -->
    + * <!ATTLIST tagdiff startTag NMTOKEN #IMPLIED >
    + * <!-- End tag of the report -->
    + * <!ATTLIST tagdiff endTag NMTOKEN #IMPLIED >
    + * <!-- Start date of the report -->
    + * <!ATTLIST tagdiff startDate NMTOKEN #IMPLIED >
    + * <!-- End date of the report -->
    + * <!ATTLIST tagdiff endDate NMTOKEN #IMPLIED >
    + *
    + * <!-- CVS tag entry -->
    + * <!ELEMENT entry ( file ) >
    + * <!-- File added, changed or removed -->
    + * <!ELEMENT file ( name, revision?, prevrevision? ) >
    + * <!-- Name of the file -->
    + * <!ELEMENT name ( #PCDATA ) >
    + * <!-- Revision number -->
    + * <!ELEMENT revision ( #PCDATA ) >
    + * <!-- Previous revision number -->
    + * <!ELEMENT prevrevision ( #PCDATA ) >
    + * 
    + * + * @author Frederic Lavigne + * @version $Revision$ $Date$ + * @ant.task name="cvstagdiff" + */ +public class CvsTagDiff extends Task { + + /** + * Token to identify a new file in the rdiff log + */ + static final String FILE_IS_NEW = " is new; current revision "; + + /** + * Token to identify a modified file in the rdiff log + */ + static final String FILE_HAS_CHANGED = " changed from revision "; + + /** + * Token to identify a removed file in the rdiff log + */ + static final String FILE_WAS_REMOVED = " is removed"; + + /** + * The cvs task which will perform the rdiff. + */ + private Cvs m_cvs; + + /** + * The cvs package/module to analyse + */ + private String m_package; + + /** + * The earliest tag from which diffs are to be included in the report. + */ + private String m_startTag; + + /** + * The latest tag from which diffs are to be included in the report. + */ + private String m_endTag; + + /** + * The earliest date from which diffs are to be included in the report. + */ + private String m_startDate; + + /** + * The latest date from which diffs are to be included in the report. + */ + private String m_endDate; + + /** + * The file in which to write the diff report. + */ + private File m_destfile; + + /** + * Used to create the temp file for cvs log + */ + private FileUtils m_fileUtils = FileUtils.newFileUtils(); + + /** + * Initialize this task. + * CvsTagDiff initializes a member cvs task in init() to perform the rdiff in execute(). + * + * @exception BuildException if an error occurs + */ + public void init() throws BuildException { + m_cvs = (Cvs)getProject().createTask("cvs"); + } + + /** + * @see org.apache.tools.ant.taskdefs.AbstractCvsTask#setCompressionLevel(int) + */ + public void setCompressionLevel(int level) { + m_cvs.setCompressionLevel(level); + } + + /** + * @see org.apache.tools.ant.taskdefs.AbstractCvsTask#setCompression(boolean) + */ + public void setCompression(boolean usecomp) { + m_cvs.setCompression(usecomp); + } + + /** + * @see org.apache.tools.ant.taskdefs.AbstractCvsTask#setCvsRoot + */ + public void setCvsRoot(String cvsRoot) { + m_cvs.setCvsRoot(cvsRoot); + } + + /** + * @see org.apache.tools.ant.taskdefs.AbstractCvsTask#setCvsRsh + */ + public void setCvsRsh(String rsh) { + m_cvs.setCvsRsh(rsh); + } + + /** + * @see org.apache.tools.ant.taskdefs.AbstractCvsTask#setPackage + */ + public void setPackage(String p) { + m_package = p; + } + + /** + * @see org.apache.tools.ant.taskdefs.AbstractCvsTask#setQuiet + */ + public void setQuiet(boolean quiet) { + m_cvs.setQuiet(quiet); + } + + /** + * @see org.apache.tools.ant.taskdefs.AbstractCvsTask#setPort + */ + public void setPort(int port) { + m_cvs.setPort(port); + } + + /** + * @see org.apache.tools.ant.taskdefs.AbstractCvsTask#setPassfile + */ + public void setPassfile(File f) { + m_cvs.setPassfile(f); + } + + /** + * @see org.apache.tools.ant.taskdefs.AbstractCvsTask#setFailOnError + */ + public void setFailOnError(boolean b) { + m_cvs.setFailOnError(b); + } + + /** + * Set the start tag. + * + * @param s the start tag. + */ + public void setStartTag(String s) { + m_startTag = s; + } + + /** + * Set the start date. + * + * @param s the start date. + */ + public void setStartDate(String s) { + m_startDate = s; + } + + /** + * Set the end tag. + * + * @param s the end tag. + */ + public void setEndTag(String s) { + m_endTag = s; + } + + /** + * Set the end date. + * + * @param s the end date. + */ + public void setEndDate(String s) { + m_endDate = s; + } + + /** + * Set the output file for the diff. + * + * @param f the output file for the diff. + */ + public void setDestFile(File f) { + m_destfile = f; + } + + /** + * Execute task. + * + * @exception BuildException if an error occurs + */ + public void execute() throws BuildException { + // validate the input parameters + validate(); + + // build the rdiff command + String rdiff = "rdiff -s " + + (m_startTag!=null?("-r " + m_startTag):("-D " + m_startDate)) + " " + + (m_endTag!=null?("-r " + m_endTag):("-D " + m_endDate)) + " " + + m_package; + log("Cvs command is " + rdiff, Project.MSG_VERBOSE); + m_cvs.setCommand(rdiff); + + File tmpFile = null; + try { + tmpFile = m_fileUtils.createTempFile("cvstagdiff", ".log", null); + m_cvs.setOutput(tmpFile); + + // run the cvs command + m_cvs.execute(); + + // parse the rdiff + CvsTagEntry[] entries = parseRDiff(tmpFile); + + // write the tag diff + writeTagDiff(entries); + + } finally { + if (tmpFile != null) { + tmpFile.delete(); + } + } + } + + /** + * Parse the tmpFile and return and array of CvsTagEntry to be written in the output. + * + * @param tmpFile the File containing the output of the cvs rdiff command + * @return the entries in the output + * @exception BuildException if an error occurs + */ + private CvsTagEntry[] parseRDiff(File tmpFile) throws BuildException { + // parse the output of the command + BufferedReader reader = null; + + try { + reader = new BufferedReader(new FileReader(tmpFile)); + + // entries are of the form: + // File module/filename is new; current revision 1.1 + // or + // File module/filename changed from revision 1.4 to 1.6 + // or + // File module/filename is removed; not included in release tag SKINLF_12 + int headerLength = 5 + m_package.length() + 1; // get rid of 'File module/" + Vector entries = new Vector(); + + String line = reader.readLine(); + int index; + CvsTagEntry entry = null; + + while (null != line) { + line = line.substring(headerLength); + + if ((index = line.indexOf(FILE_IS_NEW)) != -1) { + // it is a new file + // set the revision but not the prevrevision + String filename = line.substring(0, index); + String rev = line.substring(index + FILE_IS_NEW.length()); + + entries.add(entry = new CvsTagEntry(filename, rev)); + log(entry.toString(), Project.MSG_VERBOSE); + } else if ((index = line.indexOf(FILE_HAS_CHANGED)) != -1) { + // it is a modified file + // set the revision and the prevrevision + String filename = line.substring(0, index); + int revSeparator = line.indexOf(" to ", index); + String prevRevision = line.substring(index + FILE_HAS_CHANGED.length(), revSeparator); + String revision = line.substring(revSeparator + 4); // 4 is " to " length + + entries.add(entry = new CvsTagEntry(filename, revision, prevRevision)); + log(entry.toString(), Project.MSG_VERBOSE); + } else if ((index = line.indexOf(FILE_WAS_REMOVED)) != -1) { + // it is a removed file + String filename = line.substring(0, index); + + entries.add(entry = new CvsTagEntry(filename)); + log(entry.toString(), Project.MSG_VERBOSE); + } + line = reader.readLine(); + } + + CvsTagEntry[] array = new CvsTagEntry[entries.size()]; + entries.copyInto(array); + + return array; + } catch (IOException e) { + throw new BuildException("Error in parsing", e); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + } + } + } + } + + /** + * Write the rdiff log. + * + * @param entries a CvsTagEntry[] value + * @exception BuildException if an error occurs + */ + private void writeTagDiff(CvsTagEntry[] entries) throws BuildException { + FileOutputStream output = null; + try { + output = new FileOutputStream(m_destfile); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, "UTF-8")); + writer.println(""); + writer.print(""); + for (int i = 0, c = entries.length; i < c; i++) { + writeTagEntry(writer, entries[i]); + } + writer.println(""); + writer.flush(); + writer.close(); + } catch (UnsupportedEncodingException uee) { + log(uee.toString(), Project.MSG_ERR); + } catch (IOException ioe) { + throw new BuildException(ioe.toString(), ioe); + } finally { + if (null != output) { + try { + output.close(); + } catch (IOException ioe) { } + } + } + } + + /** + * Write a single entry to the given writer. + * + * @param writer a PrintWriter value + * @param entry a CvsTagEntry value + */ + private void writeTagEntry(PrintWriter writer, CvsTagEntry entry) { + writer.println("\t"); + writer.println("\t\t"); + writer.println("\t\t\t" + entry.getFile() + ""); + if (entry.getRevision() != null) { + writer.println("\t\t\t" + entry.getRevision() + ""); + } + if (entry.getPreviousRevision() != null) { + writer.println("\t\t\t" + entry.getPreviousRevision() + ""); + } + writer.println("\t\t"); + writer.println("\t"); + } + + /** + * Validate the parameters specified for task. + * + * @exception BuildException if a parameter is not correctly set + */ + private void validate() throws BuildException { + if (null == m_package) { + throw new BuildException("Package/module must be set."); + } + + if (null == m_destfile) { + throw new BuildException("Destfile must be set."); + } + + if (null == m_startTag && null == m_startDate) { + throw new BuildException("Start tag or start date must be set."); + } + + if (null != m_startTag && null != m_startDate) { + throw new BuildException("Only one of start tag and start date must be set."); + } + + if (null == m_endTag && null == m_endDate) { + throw new BuildException("End tag or end date must be set."); + } + + if (null != m_endTag && null != m_endDate) { + throw new BuildException("Only one of end tag and end date must be set."); + } + } + + /** + * Holds the information of a line of rdiff + */ + static class CvsTagEntry { + String m_filename; + String m_prevRevision; + String m_revision; + + public CvsTagEntry(String filename) { + this(filename, null, null); + } + + public CvsTagEntry(String filename, String revision) { + this(filename, revision, null); + } + + public CvsTagEntry(String filename, String revision, String prevRevision) { + m_filename = filename; + m_revision = revision; + m_prevRevision = prevRevision; + } + + public String getFile() { + return m_filename; + } + + public String getRevision() { + return m_revision; + } + + public String getPreviousRevision() { + return m_prevRevision; + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append(m_filename); + if ((m_revision == null) && (m_prevRevision == null)) { + buffer.append(" was removed"); + } else if (m_revision != null && m_prevRevision == null) { + buffer.append(" is new; current revision is ").append(m_revision); + } else if (m_revision != null && m_prevRevision != null) { + buffer.append(" has changed from ").append(m_prevRevision).append(" to ").append(m_revision); + } + return buffer.toString(); + } + } + +}