bodewig 2005/02/15 05:30:51 Modified: proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn SvnEntry.java antlib.xml Added: proposal/sandbox/svn/docs revisiondiff.html proposal/sandbox/svn/src/etc revisiondiff.xsl proposal/sandbox/svn/src/etc/testcases revisiondiff.xml proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn SvnRevisionDiff.java Log: Add revisiondiff to match cvstagdiff, well, sort-of Revision Changes Path 1.1 ant/proposal/sandbox/svn/docs/revisiondiff.html Index: revisiondiff.html =================================================================== <html> <head> <meta http-equiv="Content-Language" content="en-us"> <title>RevisionDiff Task</title> </head> <body> <h2><a name="revisiondiff">RevisionDiff</a></h2> <h3>Description</h3> <p>Generates an XML-formatted report file of the changes between two revisions recorded in a <a href="http://subversion.tigris.org/" target="_top">Subversion</a> repository. </p> <p><b>Important:</b> This task needs "svn" on the path. If it isn't, you will get an error (such as error 2 on windows). If <code><svn></code> doesn't work, try to execute <code>svn.exe</code> from the command line in the target directory in which you are working.</p> <h3>Parameters</h3> <table border="1" cellpadding="2" cellspacing="0"> <tr> <td valign="top"><b>Attribute</b></td> <td valign="top"><b>Description</b></td> <td align="center" valign="top"><b>Required</b></td> </tr> <tr> <td valign="top">start</td> <td valign="top">The earliest revision from which diffs are to be included in the report.</td> <td align="center" valign="top">Yes.</td> </tr> <tr> <td valign="top">end</td> <td valign="top">The latest revision from which diffs are to be included in the report.</td> <td align="center" valign="top">Yes.</td> </tr> <tr> <td valign="top">destfile</td> <td valign="top">The file in which to write the diff report.</td> <td align="center" valign="top">Yes</td> </tr> </table> <h3>Parameters inherited from the <code>svn</code> task</h3> <table border="1" cellpadding="2" cellspacing="0"> <tr> <td valign="top"><b>Attribute</b></td> <td valign="top"><b>Description</b></td> <td align="center" valign="top"><b>Required</b></td> </tr> <tr> <td valign="top">svnURL</td> <td valign="top">the svn URL to diff.</td> <td align="center" valign="top">No</td> </tr> <tr> <td valign="top">failonerror</td> <td valign="top">Stop the buildprocess if the command exits with a returncode other than 0. Defaults to false</td> <td align="center" valign="top">No</td> </tr> </table> <h3>Examples</h3> <pre> <revisiondiff svnURL="http://svn.apache.org/repos/asf/jakarta/bcel/trunk" destfile="diff.xml" start="152904" end="153682" /></pre> <p>Generates a revisiondiff report for all the changes that have been made in the <code>Apache BCEL</code> module between the revisions <code>152904</code> and <code>153682</code>. It writes these changes into the file <code>diff.xml</code>.</p> <pre> <revisiondiff destfile="diff.xml" package="ant" start="{2002-01-01}" end="{2002-02-01}" dest="my-working-copy-of-BCEL" /></pre> <p>Generates a diff report for all the changes that have been made in the <code>Apache BCEL</code> module in january 2002. In this example <code>svnURL</code> has not been set, it is assumed that <code>my-working-copy-of-BCEL</code> contains a checked out copy of the BCEL module. It writes these changes into the file <code>diff.xml</code>.</p> <h4>Generate Report</h4> <p>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.</p> <pre> <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> </pre> <h4>(Shortened) Example Output</h4> <pre> <?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> </pre> <hr><p align="center">Copyright © 2005 The Apache Software Foundation. All rights Reserved.</p> </body> </html> 1.1 ant/proposal/sandbox/svn/src/etc/revisiondiff.xsl Index: revisiondiff.xsl =================================================================== <!-- 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. --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:param name="title"/> <xsl:param name="repo"/> <xsl:output method="html" indent="yes"/> <!-- Copy standard document elements. Elements that should be ignored must be filtered by apply-templates tags. --> <xsl:template match="*"> <xsl:copy> <xsl:copy-of select="attribute::*[. != '']"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> <xsl:template match="revisiondiff"> <HTML> <HEAD> <TITLE><xsl:value-of select="$title"/></TITLE> </HEAD> <BODY link="#000000" alink="#000000" vlink="#000000" text="#000000"> <style type="text/css"> body, p { font-family: verdana,arial,helvetica; font-size: 80%; color:#000000; } .dateAndAuthor { font-family: verdana,arial,helvetica; font-size: 80%; font-weight: bold; text-align:left; background:#a6caf0; } tr, td{ font-family: verdana,arial,helvetica; font-size: 80%; background:#eeeee0; } </style> <h1> <a name="top"><xsl:value-of select="$title"/></a> </h1> diff between <xsl:value-of select="@start"/> and <xsl:value-of select="@end"/> <p align="right">Designed for use with <a href="http://ant.apache.org/">Apache Ant</a>.</p> <hr size="2"/> <a name="TOP"/> <table width="100%"> <tr> <td align="right"> <a href="#New">New Files</a> | <a href="#Modified">Modified Files</a> | <a href="#Removed">Removed Files</a> </td> </tr> </table> <TABLE BORDER="0" WIDTH="100%" CELLPADDING="3" CELLSPACING="1"> <xsl:call-template name="show-paths"> <xsl:with-param name="title">New Files</xsl:with-param> <xsl:with-param name="anchor">New</xsl:with-param> <xsl:with-param name="paths" select=".//path[action='added']"/> </xsl:call-template> <xsl:call-template name="show-paths"> <xsl:with-param name="title">Modified Files</xsl:with-param> <xsl:with-param name="anchor">Modified</xsl:with-param> <xsl:with-param name="paths" select=".//path[action='modified']"/> </xsl:call-template> <xsl:call-template name="show-paths"> <xsl:with-param name="title">Removed Files</xsl:with-param> <xsl:with-param name="anchor">Removed</xsl:with-param> <xsl:with-param name="paths" select=".//path[action='deleted']"/> </xsl:call-template> </TABLE> </BODY> </HTML> </xsl:template> <xsl:template name="show-paths"> <xsl:param name="title"/> <xsl:param name="anchor"/> <xsl:param name="paths"/> <TR> <TD colspan="2" class="dateAndAuthor"> <a> <xsl:attribute name="name"><xsl:value-of select="$anchor"/></xsl:attribute> <xsl:value-of select="$title"/> - <xsl:value-of select="count($paths)"/> entries </a> <a href="#TOP">(back to top)</a> </TD> </TR> <TR> <TD width="20"> <xsl:text> </xsl:text> </TD> <TD> <ul> <xsl:apply-templates select="$paths"/> </ul> </TD> </TR> </xsl:template> <xsl:template match="path"> <li> <a target="_new"> <xsl:attribute name="href"><xsl:value-of select="$repo"/>/<xsl:value-of select="name" /></xsl:attribute> <xsl:value-of select="name" /> </a> </li> </xsl:template> <!-- Any elements within a msg are processed, so that we can preserve HTML tags. --> <xsl:template match="msg"> <b><xsl:apply-templates/></b> </xsl:template> </xsl:stylesheet> 1.1 ant/proposal/sandbox/svn/src/etc/testcases/revisiondiff.xml Index: revisiondiff.xml =================================================================== <?xml version="1.0"?> <!-- 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. --> <project name="revisiondiff-test" basedir="../../../" default="diff" xmlns:svn="antlib:org.apache.tools.ant.taskdefs.svn"> <property name="tmpdir" value="tmpdir"/> <property name="trunkdir" value="${tmpdir}/trunk"/> <property name="file" value="ebcdic.h"/> <target name="dir-prep"> <mkdir dir="${tmpdir}"/> </target> <target name="setup" depends="dir-prep"> <svn:svn svnURL="http://svn.apache.org/repos/asf/jakarta/bcel/trunk" dest="${tmpdir}"/> </target> <target name="diff" depends="setup"> <svn:revisiondiff failonerror="true" dest="${trunkdir}" destfile="${tmpdir}/diff.xml" start="152904" end="153682"/> </target> <target name="diff-using-url" depends="dir-prep"> <svn:revisiondiff failonerror="true" svnURL="http://svn.apache.org/repos/asf/jakarta/bcel/trunk" destfile="${tmpdir}/diff.xml" start="152904" end="153682"/> </target> <target name="report"> <!--target name="report" depends="diff-using-url"--> <style in="${tmpdir}/diff.xml" out="${tmpdir}/diff.html" style="src/etc/revisiondiff.xsl"> <param name="title" expression="Jakarta BCEL diff"/> <param name="repo" expression="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"/> </style> </target> <target name="cleanup"> <delete dir="${tmpdir}" /> </target> </project> 1.3 +8 -0 ant/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java Index: SvnEntry.java =================================================================== RCS file: /home/cvs/ant/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- SvnEntry.java 15 Feb 2005 11:12:15 -0000 1.2 +++ SvnEntry.java 15 Feb 2005 13:30:49 -0000 1.3 @@ -147,6 +147,14 @@ } } + 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; } 1.3 +4 -0 ant/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml Index: antlib.xml =================================================================== RCS file: /home/cvs/ant/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- antlib.xml 14 Feb 2005 13:28:33 -0000 1.2 +++ antlib.xml 15 Feb 2005 13:30:49 -0000 1.3 @@ -23,4 +23,8 @@ name="changelog" classname="org.apache.tools.ant.taskdefs.svn.SvnChangeLogTask" /> + <taskdef + name="revisiondiff" + classname="org.apache.tools.ant.taskdefs.svn.SvnRevisionDiff" + /> </antlib> 1.1 ant/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnRevisionDiff.java Index: SvnRevisionDiff.java =================================================================== /* * 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. * <PRE> * <!-- 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)> * </PRE> * * @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 <code>SvnRevisionEntry[]</code> 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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); writer.print("<revisiondiff "); if (mystartRevision != null) { writer.print("start=\"" + mystartRevision + "\" "); } if (myendRevision != null) { writer.print("end=\"" + myendRevision + "\" "); } if (getSvnURL() != null) { writer.print("svnurl=\"" + getSvnURL() + "\" "); } writer.println(">"); for (int i = 0, c = entries.length; i < c; i++) { writeRevisionEntry(writer, entries[i]); } writer.println("</revisiondiff>"); 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 <code>PrintWriter</code> value * @param entry a <code>SvnRevisionEntry</code> value */ private void writeRevisionEntry(PrintWriter writer, SvnEntry.Path entry) { writer.println("\t<path>"); writer.println("\t\t<name><![CDATA[" + entry.getName() + "]]></name>"); writer.println("\t\t<action>" + entry.getActionDescription() + "</action>"); writer.println("\t</path>"); } /** * 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."); } } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]