From 67bb0f072877df03aeadcbfe0b724525eda2d17b Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Tue, 15 Feb 2005 13:30:49 +0000 Subject: [PATCH] Add revisiondiff to match cvstagdiff, well, sort-of git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277668 13f79535-47bb-0310-9956-ffa450edef68 --- proposal/sandbox/svn/docs/revisiondiff.html | 129 +++++++ proposal/sandbox/svn/src/etc/revisiondiff.xsl | 140 ++++++++ .../svn/src/etc/testcases/revisiondiff.xml | 60 ++++ .../tools/ant/taskdefs/svn/SvnEntry.java | 8 + .../ant/taskdefs/svn/SvnRevisionDiff.java | 321 ++++++++++++++++++ .../apache/tools/ant/taskdefs/svn/antlib.xml | 4 + 6 files changed, 662 insertions(+) create mode 100644 proposal/sandbox/svn/docs/revisiondiff.html create mode 100644 proposal/sandbox/svn/src/etc/revisiondiff.xsl create mode 100644 proposal/sandbox/svn/src/etc/testcases/revisiondiff.xml create mode 100644 proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnRevisionDiff.java diff --git a/proposal/sandbox/svn/docs/revisiondiff.html b/proposal/sandbox/svn/docs/revisiondiff.html new file mode 100644 index 000000000..f9c61e9eb --- /dev/null +++ b/proposal/sandbox/svn/docs/revisiondiff.html @@ -0,0 +1,129 @@ + + + +RevisionDiff Task + + +

RevisionDiff

+

Description

+ +

Generates an XML-formatted report file of the changes between two +revisions recorded in a Subversion repository.

+ +

Important: This task needs "svn" on the path. If it isn't, +you will get an error (such as error 2 on windows). If +<svn> doesn't work, try to execute +svn.exe from the command line in the target directory in +which you are working.

+ +

Parameters

+ + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
startThe earliest revision from which diffs are to be + included in the report.Yes.
endThe latest revision from which diffs are to be + included in the report.Yes.
destfileThe file in which to write the diff report.Yes
+ +

Parameters inherited from the svn task

+ + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
svnURLthe svn URL to diff.No
failonerrorStop the buildprocess if the command exits with a + returncode other than 0. Defaults to falseNo
+ +

Examples

+
  <revisiondiff
+                svnURL="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"
+                destfile="diff.xml"
+                start="152904"
+                end="153682"
+  />
+ +

Generates a revisiondiff report for all the changes that have been +made in the Apache BCEL module between the revisions +152904 and 153682. It writes these changes +into the file diff.xml.

+ +
  <revisiondiff
+                destfile="diff.xml"
+                package="ant"
+                start="{2002-01-01}"
+                end="{2002-02-01}"
+                dest="my-working-copy-of-BCEL"
+  />
+ +

Generates a diff report for all the changes that have been made in +the Apache BCEL module in january 2002. In this example +svnURL has not been set, it is assumed that +my-working-copy-of-BCEL contains a checked out copy of +the BCEL module. It writes these changes into the file +diff.xml.

+ +

Generate Report

+ +

This antlib 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="diff.xml" 
+               out="diff.html" 
+               style="your-path-to/etc/revisiondiff.xsl">
+          <param name="title" expression="Jakarta BCEL diff"/>
+          <param name="repo" expression="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"/>
+        </style>
+
+ +

(Shortened) Example Output

+
+<?xml version="1.0" encoding="UTF-8"?>
+<revisiondiff start="153872" end="152873" svnurl="http://svn.apache.org/repos/asf/jakarta/bcel/trunk" >
+  <path>
+    <name><![CDATA[LICENSE.txt]]></name>
+    <action>modified</action>
+  </path>
+  <path>
+    <name><![CDATA[NOTICE.txt]]></name>
+    <action>deleted</action>
+  </path>
+</revisiondiff>
+
+ +

Copyright © 2005 The Apache Software Foundation. All rights +Reserved.

+ + + + diff --git a/proposal/sandbox/svn/src/etc/revisiondiff.xsl b/proposal/sandbox/svn/src/etc/revisiondiff.xsl new file mode 100644 index 000000000..a0391c33b --- /dev/null +++ b/proposal/sandbox/svn/src/etc/revisiondiff.xsl @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + <xsl:value-of select="$title"/> + + + +

+ +

+ diff between and +

Designed for use with Apache Ant.

+
+ + + + + +
+ New Files | + Modified Files | + Removed Files +
+ + + New Files + New + + + + + Modified Files + Modified + + + + + Removed Files + Removed + + +
+ + + +
+ + + + + + + + + + - entries + + (back to top) + + + + + + + +
    + +
+ + + + + +
  • + + / + + +
  • +
    + + + + + + +
    diff --git a/proposal/sandbox/svn/src/etc/testcases/revisiondiff.xml b/proposal/sandbox/svn/src/etc/testcases/revisiondiff.xml new file mode 100644 index 000000000..fb17d4383 --- /dev/null +++ b/proposal/sandbox/svn/src/etc/testcases/revisiondiff.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java index 1602f43aa..7da4f3fa8 100644 --- a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java +++ b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java @@ -147,6 +147,14 @@ public class SvnEntry { } } + public Path(final String name, final int action) { + this.name = name; + if (action != ADDED && action != DELETED && action != MODIFIED) { + throw new IllegalArgumentException("Unkown action; " + action); + } + this.action = action; + } + public String getName() { return name; } diff --git a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnRevisionDiff.java b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnRevisionDiff.java new file mode 100644 index 000000000..e347a1f6f --- /dev/null +++ b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnRevisionDiff.java @@ -0,0 +1,321 @@ +/* + * Copyright 2005 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. + * + */ +package org.apache.tools.ant.taskdefs.svn; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.StringTokenizer; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.util.FileUtils; + +/** + * Examines the output of svn diff between two revisions. + * + * It produces an XML output representing the list of changes. + *
    + * <!-- Root element -->
    + * <!ELEMENT revisiondiff ( paths? ) >
    + * <!-- Start revision of the report -->
    + * <!ATTLIST revisiondiff startRevision NMTOKEN #IMPLIED >
    + * <!-- End revision of the report -->
    + * <!ATTLIST revisiondiff endRevision NMTOKEN #IMPLIED >
    + * <!-- Start date of the report -->
    + *
    + * <!-- Path added, changed or removed -->
    + * <!ELEMENT path ( name,action ) >
    + * <!-- Name of the file -->
    + * <!ELEMENT name ( #PCDATA ) >
    + * <!ELEMENT action (added|modified|deleted)>
    + * 
    + * + * @ant.task name="svnrevisiondiff" + */ +public class SvnRevisionDiff extends AbstractSvnTask { + + /** + * Used to create the temp file for svn log + */ + private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); + + /** + * Token to identify the word file in the rdiff log + */ + static final String INDEX = "Index: "; + /** + * Token to identify a deleted file based on the Index line. + */ + static final String DELETED = " (deleted)"; + + /** + * Token to identify added files based on the diff line. + */ + static final String IS_NEW = "\t(revision 0)"; + + /** + * Token that starts diff line of old revision. + */ + static final String DASHES = "--- "; + + /** + * The earliest revision from which diffs are to be included in the report. + */ + private String mystartRevision; + + /** + * The latest revision from which diffs are to be included in the report. + */ + private String myendRevision; + + /** + * The file in which to write the diff report. + */ + private File mydestfile; + + /** + * Set the start revision. + * + * @param s the start revision. + */ + public void setStart(String s) { + mystartRevision = s; + } + + /** + * Set the end revision. + * + * @param s the end revision. + */ + public void setEnd(String s) { + myendRevision = s; + } + + /** + * Set the output file for the diff. + * + * @param f the output file for the diff. + */ + public void setDestFile(File f) { + mydestfile = f; + } + + /** + * Execute task. + * + * @exception BuildException if an error occurs + */ + public void execute() throws BuildException { + // validate the input parameters + validate(); + + // build the rdiff command + setSubCommand("diff"); + setRevision(mystartRevision + ":" + myendRevision); + addSubCommandArgument("--no-diff-deleted"); + + File tmpFile = null; + try { + tmpFile = + FILE_UTILS.createTempFile("svnrevisiondiff", ".log", null); + tmpFile.deleteOnExit(); + setOutput(tmpFile); + + // run the svn command + super.execute(); + + // parse the rdiff + SvnEntry.Path[] entries = parseDiff(tmpFile); + + // write the revision diff + writeRevisionDiff(entries); + + } finally { + if (tmpFile != null) { + tmpFile.delete(); + } + } + } + + /** + * Parse the tmpFile and return and array of SvnRevisionEntry to be + * written in the output. + * + * @param tmpFile the File containing the output of the svn rdiff command + * @return the entries in the output + * @exception BuildException if an error occurs + */ + private SvnEntry.Path[] parseDiff(File tmpFile) throws BuildException { + // parse the output of the command + BufferedReader reader = null; + + try { + reader = new BufferedReader(new FileReader(tmpFile)); + ArrayList entries = new ArrayList(); + + String line = reader.readLine(); + String name = null; + String currDiffLine = null; + boolean deleted = false; + boolean added = false; + + while (null != line) { + if (line.length() > INDEX.length()) { + if (line.startsWith(INDEX)) { + if (name != null) { + SvnEntry.Path p = + new SvnEntry.Path(name, + deleted + ? SvnEntry.Path.DELETED + : (added + ? SvnEntry.Path.ADDED + : SvnEntry.Path.MODIFIED) + ); + entries.add(p); + deleted = added = false; + } + + name = line.substring(INDEX.length()); + if (line.endsWith(DELETED)) { + name = name.substring(0, name.length() + - DELETED.length()); + deleted = true; + } + + currDiffLine = DASHES + name; + } else if (currDiffLine != null + && line.startsWith(currDiffLine) + && line.endsWith(IS_NEW)) { + added = true; + } + } + line = reader.readLine(); + } + if (name != null) { + SvnEntry.Path p = new SvnEntry.Path(name, + deleted + ? SvnEntry.Path.DELETED + : (added + ? SvnEntry.Path.ADDED + : SvnEntry.Path.MODIFIED) + ); + entries.add(p); + } + + SvnEntry.Path[] array = (SvnEntry.Path[]) + entries.toArray(new SvnEntry.Path[entries.size()]); + return array; + } catch (IOException e) { + throw new BuildException("Error in parsing", e); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + log(e.toString(), Project.MSG_ERR); + } + } + } + } + + /** + * Write the rdiff log. + * + * @param entries a SvnRevisionEntry[] value + * @exception BuildException if an error occurs + */ + private void writeRevisionDiff(SvnEntry.Path[] entries) throws BuildException { + FileOutputStream output = null; + try { + output = new FileOutputStream(mydestfile); + PrintWriter writer = new PrintWriter( + new OutputStreamWriter(output, "UTF-8")); + writer.println(""); + writer.print(""); + for (int i = 0, c = entries.length; i < c; i++) { + writeRevisionEntry(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) { + log(ioe.toString(), Project.MSG_ERR); + } + } + } + } + + /** + * Write a single entry to the given writer. + * + * @param writer a PrintWriter value + * @param entry a SvnRevisionEntry value + */ + private void writeRevisionEntry(PrintWriter writer, SvnEntry.Path entry) { + writer.println("\t"); + writer.println("\t\t"); + writer.println("\t\t" + entry.getActionDescription() + + ""); + 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 == mydestfile) { + throw new BuildException("Destfile must be set."); + } + + if (null == mystartRevision) { + throw new BuildException("Start revision or start date must be set."); + } + + if (null == myendRevision) { + throw new BuildException("End revision or end date must be set."); + } + } +} diff --git a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml index 400e8f726..d78dde35a 100644 --- a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml +++ b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml @@ -23,4 +23,8 @@ name="changelog" classname="org.apache.tools.ant.taskdefs.svn.SvnChangeLogTask" /> +