git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277673 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -100,7 +100,7 @@ illustrates how to generate a HTML report from the XML report.</p> | |||||
| <pre> | <pre> | ||||
| <style in="diff.xml" | <style in="diff.xml" | ||||
| out="diff.html" | out="diff.html" | ||||
| style="your-path-to/etc/revisiondiff.xsl"> | |||||
| style="your-path-to/etc/diff.xsl"> | |||||
| <param name="title" expression="Jakarta BCEL diff"/> | <param name="title" expression="Jakarta BCEL diff"/> | ||||
| <param name="repo" expression="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"/> | <param name="repo" expression="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"/> | ||||
| </style> | </style> | ||||
| @@ -0,0 +1,158 @@ | |||||
| <html> | |||||
| <head> | |||||
| <meta http-equiv="Content-Language" content="en-us"> | |||||
| <title>RevisionDiff Task</title> | |||||
| </head> | |||||
| <body> | |||||
| <h2><a name="tagdiff">TagDiff</a></h2> | |||||
| <h3>Description</h3> | |||||
| <p>Generates an XML-formatted report file of the changes between two | |||||
| tags 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> | |||||
| <p>This task assumes that your repository follows the best-practice | |||||
| layout of</p> | |||||
| <pre> | |||||
| BASEURL | |||||
| | | |||||
| | | |||||
| -----> trunk | |||||
| -----> tags | |||||
| | | |||||
| | | |||||
| ----------> tag1 | |||||
| ----------> tag2 | |||||
| </pre> | |||||
| <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">tag1</td> | |||||
| <td valign="top">The first tag.</td> | |||||
| <td align="center" valign="top">Yes.</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">tag2</td> | |||||
| <td valign="top">The second tag.</td> | |||||
| <td align="center" valign="top">No, defaults to "trunk/"</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> | |||||
| <tr> | |||||
| <td valign="top">baseURL</td> | |||||
| <td valign="top">The baseURL of the repository, used to calculate | |||||
| the two URLs to compare.</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">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> | |||||
| <tagdiff failonerror="true" | |||||
| baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/" | |||||
| destfile="diff.xml" | |||||
| tag1="initial" | |||||
| tag2="BCEL_5_0" | |||||
| /> | |||||
| </pre> | |||||
| <p>Generates a tagdiff report for all the changes that have been | |||||
| made in the <code>Apache BCEL</code> module between the tags | |||||
| <code>initial</code> and <code>BCEL_5_0</code>. It writes these changes | |||||
| into the file <code>diff.xml</code>.</p> | |||||
| <pre> | |||||
| <tagdiff failonerror="true" | |||||
| baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/" | |||||
| destfile="diff.xml" | |||||
| tag1="BCEL_5_0" | |||||
| tag2="trunk" | |||||
| /> | |||||
| </pre> | |||||
| <p>Generates a tagdiff report for all the changes that have been made | |||||
| in the <code>Apache BCEL</code> module between the tag | |||||
| <code>BCEL_5_0</code> and the <code>trunk</code>. It writes these | |||||
| changes into the file <code>diff.xml</code>.</p> | |||||
| <pre> | |||||
| <tagdiff failonerror="true" | |||||
| baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/" | |||||
| destfile="diff.xml" | |||||
| tag1="BCEL_5_0" | |||||
| /> | |||||
| </pre> | |||||
| <p>Does the same, using <code>trunk</code> as <code>tag2</code> | |||||
| implicitly.</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/diff.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"?> | |||||
| <tagdiff tag1="BCEL_5_0" svnurl="http://svn.apache.org/repos/asf/jakarta/bcel/" > | |||||
| <path> | |||||
| <name><![CDATA[default.properties]]></name> | |||||
| <action>added</action> | |||||
| </path> | |||||
| <path> | |||||
| <name><![CDATA[xdocs/images/classloader.gif]]></name> | |||||
| <action>modified</action> | |||||
| </path> | |||||
| <path> | |||||
| <name><![CDATA[README]]></name> | |||||
| <action>deleted</action> | |||||
| </path> | |||||
| </tagdiff> | |||||
| </pre> | |||||
| <hr><p align="center">Copyright © 2005 The Apache Software Foundation. All rights | |||||
| Reserved.</p> | |||||
| </body> | |||||
| </html> | |||||
| @@ -32,7 +32,7 @@ | |||||
| </xsl:copy> | </xsl:copy> | ||||
| </xsl:template> | </xsl:template> | ||||
| <xsl:template match="revisiondiff"> | |||||
| <xsl:template match="revisiondiff|tagdiff"> | |||||
| <HTML> | <HTML> | ||||
| <HEAD> | <HEAD> | ||||
| <TITLE><xsl:value-of select="$title"/></TITLE> | <TITLE><xsl:value-of select="$title"/></TITLE> | ||||
| @@ -60,7 +60,7 @@ | |||||
| <h1> | <h1> | ||||
| <a name="top"><xsl:value-of select="$title"/></a> | <a name="top"><xsl:value-of select="$title"/></a> | ||||
| </h1> | </h1> | ||||
| diff between <xsl:value-of select="@start"/> and <xsl:value-of select="@end"/> | |||||
| diff between <xsl:value-of select="@start"/><xsl:value-of select="@tag1"/> and <xsl:value-of select="@end"/><xsl:value-of select="@tag2"/> | |||||
| <p align="right">Designed for use with <a href="http://ant.apache.org/">Apache Ant</a>.</p> | <p align="right">Designed for use with <a href="http://ant.apache.org/">Apache Ant</a>.</p> | ||||
| <hr size="2"/> | <hr size="2"/> | ||||
| <a name="TOP"/> | <a name="TOP"/> | ||||
| @@ -46,7 +46,7 @@ | |||||
| <target name="report" depends="diff-using-url"> | <target name="report" depends="diff-using-url"> | ||||
| <style in="${tmpdir}/diff.xml" | <style in="${tmpdir}/diff.xml" | ||||
| out="${tmpdir}/diff.html" | out="${tmpdir}/diff.html" | ||||
| style="src/etc/revisiondiff.xsl"> | |||||
| style="src/etc/diff.xsl"> | |||||
| <param name="title" expression="Jakarta BCEL diff"/> | <param name="title" expression="Jakarta BCEL diff"/> | ||||
| <param name="repo" expression="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"/> | <param name="repo" expression="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"/> | ||||
| </style> | </style> | ||||
| @@ -0,0 +1,63 @@ | |||||
| <?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-with-implicit-trunk" | |||||
| xmlns:svn="antlib:org.apache.tools.ant.taskdefs.svn"> | |||||
| <property name="tmpdir" value="tmpdir"/> | |||||
| <target name="dir-prep"> | |||||
| <mkdir dir="${tmpdir}"/> | |||||
| </target> | |||||
| <target name="diff-with-two-tags" depends="dir-prep"> | |||||
| <svn:tagdiff failonerror="true" | |||||
| baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/" | |||||
| destfile="${tmpdir}/diff.xml" | |||||
| tag2="BCEL_5_0" tag1="initial"/> | |||||
| </target> | |||||
| <target name="diff-with-explicit-trunk" depends="dir-prep"> | |||||
| <svn:tagdiff failonerror="true" | |||||
| baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/" | |||||
| destfile="${tmpdir}/diff.xml" | |||||
| tag1="BCEL_5_0" tag2="trunk"/> | |||||
| </target> | |||||
| <target name="diff-with-implicit-trunk" depends="dir-prep"> | |||||
| <svn:tagdiff failonerror="true" | |||||
| baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/" | |||||
| destfile="${tmpdir}/diff.xml" | |||||
| tag1="BCEL_5_0"/> | |||||
| </target> | |||||
| <!--target name="report" depends="diff-with-implicit-trunk"--> | |||||
| <target name="report"> | |||||
| <style in="/tmp/diff.xml" | |||||
| out="/tmp/diff.html" | |||||
| style="src/etc/diff.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> | |||||
| @@ -0,0 +1,196 @@ | |||||
| /* | |||||
| * 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; | |||||
| /** | |||||
| * Parses the output of a svn diff command and/or writes an XML report | |||||
| * based on such a diff output. | |||||
| * | |||||
| * It produces an XML output representing the list of changes. | |||||
| */ | |||||
| final class SvnDiffHandler { | |||||
| /** | |||||
| * Token to identify the word file in the rdiff log | |||||
| */ | |||||
| private static final String INDEX = "Index: "; | |||||
| /** | |||||
| * Token to identify a deleted file based on the Index line. | |||||
| */ | |||||
| private static final String DELETED = " (deleted)"; | |||||
| /** | |||||
| * Token to identify added files based on the diff line. | |||||
| */ | |||||
| private static final String IS_NEW = "\t(revision 0)"; | |||||
| /** | |||||
| * Token that starts diff line of old revision. | |||||
| */ | |||||
| private static final String DASHES = "--- "; | |||||
| /** | |||||
| * Parse the tmpFile and return and array of entries 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 | |||||
| */ | |||||
| static 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 { | |||||
| FileUtils.close(reader); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Write the diff log. | |||||
| * | |||||
| * @param entries a <code>SvnRevisionEntry[]</code> value | |||||
| * @exception BuildException if an error occurs | |||||
| */ | |||||
| static void writeDiff(File destFile, SvnEntry.Path[] entries, | |||||
| String rootElementName, | |||||
| String tag1Name, String tag1Value, | |||||
| String tag2Name, String tag2Value, | |||||
| String svnURL) throws BuildException { | |||||
| FileOutputStream output = null; | |||||
| try { | |||||
| output = new FileOutputStream(destFile); | |||||
| PrintWriter writer = new PrintWriter( | |||||
| new OutputStreamWriter(output, "UTF-8")); | |||||
| writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); | |||||
| writer.print("<" + rootElementName + " "); | |||||
| if (tag1Name != null && tag1Value != null) { | |||||
| writer.print(tag1Name + "=\"" + tag1Value + "\" "); | |||||
| } | |||||
| if (tag2Name != null && tag2Value != null) { | |||||
| writer.print(tag2Name + "=\"" + tag2Value + "\" "); | |||||
| } | |||||
| if (svnURL != null) { | |||||
| writer.print("svnurl=\"" + svnURL + "\" "); | |||||
| } | |||||
| writer.println(">"); | |||||
| for (int i = 0, c = entries.length; i < c; i++) { | |||||
| writeRevisionEntry(writer, entries[i]); | |||||
| } | |||||
| writer.println("</" + rootElementName + ">"); | |||||
| writer.flush(); | |||||
| writer.close(); | |||||
| } catch (UnsupportedEncodingException uee) { | |||||
| throw new BuildException(uee); | |||||
| } catch (IOException ioe) { | |||||
| throw new BuildException(ioe.toString(), ioe); | |||||
| } finally { | |||||
| FileUtils.close(output); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Write a single entry to the given writer. | |||||
| * | |||||
| * @param writer a <code>PrintWriter</code> value | |||||
| * @param entry a <code>SvnRevisionEntry</code> value | |||||
| */ | |||||
| private static 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>"); | |||||
| } | |||||
| } | |||||
| @@ -39,10 +39,11 @@ import org.apache.tools.ant.util.FileUtils; | |||||
| * <!-- Root element --> | * <!-- Root element --> | ||||
| * <!ELEMENT revisiondiff ( paths? ) > | * <!ELEMENT revisiondiff ( paths? ) > | ||||
| * <!-- Start revision of the report --> | * <!-- Start revision of the report --> | ||||
| * <!ATTLIST revisiondiff startRevision NMTOKEN #IMPLIED > | |||||
| * <!ATTLIST revisiondiff start NMTOKEN #IMPLIED > | |||||
| * <!-- End revision of the report --> | * <!-- End revision of the report --> | ||||
| * <!ATTLIST revisiondiff endRevision NMTOKEN #IMPLIED > | |||||
| * <!-- Start date of the report --> | |||||
| * <!ATTLIST revisiondiff end NMTOKEN #IMPLIED > | |||||
| * <!-- Subversion URL if known --> | |||||
| * <!ATTLIST revisiondiff svnurl NMTOKEN #IMPLIED > | |||||
| * | * | ||||
| * <!-- Path added, changed or removed --> | * <!-- Path added, changed or removed --> | ||||
| * <!ELEMENT path ( name,action ) > | * <!ELEMENT path ( name,action ) > | ||||
| @@ -60,25 +61,6 @@ public class SvnRevisionDiff extends AbstractSvnTask { | |||||
| */ | */ | ||||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | 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. | * The earliest revision from which diffs are to be included in the report. | ||||
| */ | */ | ||||
| @@ -145,12 +127,13 @@ public class SvnRevisionDiff extends AbstractSvnTask { | |||||
| // run the svn command | // run the svn command | ||||
| super.execute(); | super.execute(); | ||||
| // parse the rdiff | |||||
| SvnEntry.Path[] entries = parseDiff(tmpFile); | |||||
| // parse the diff | |||||
| SvnEntry.Path[] entries = SvnDiffHandler.parseDiff(tmpFile); | |||||
| // write the revision diff | // write the revision diff | ||||
| writeRevisionDiff(entries); | |||||
| SvnDiffHandler.writeDiff(mydestfile, entries, "revisiondiff", | |||||
| "start", mystartRevision, | |||||
| "end", myendRevision, getSvnURL()); | |||||
| } finally { | } finally { | ||||
| if (tmpFile != null) { | if (tmpFile != null) { | ||||
| tmpFile.delete(); | tmpFile.delete(); | ||||
| @@ -158,148 +141,6 @@ public class SvnRevisionDiff extends AbstractSvnTask { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * 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. | * Validate the parameters specified for task. | ||||
| * | * | ||||
| @@ -0,0 +1,210 @@ | |||||
| /* | |||||
| * 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 tags or a tag and trunk. | |||||
| * | |||||
| * <p>This task only works if you follow the best-practice structure of | |||||
| * <pre> | |||||
| * BASEURL | |||||
| * | | |||||
| * | | |||||
| * -----> trunk | |||||
| * -----> tags | |||||
| * | | |||||
| * | | |||||
| * ----------> tag1 | |||||
| * ----------> tag2 | |||||
| * </pre> | |||||
| * | |||||
| * It produces an XML output representing the list of changes. | |||||
| * <PRE> | |||||
| * <!-- Root element --> | |||||
| * <!ELEMENT tagdiff ( paths? ) > | |||||
| * <!-- First tag --> | |||||
| * <!ATTLIST tagdiff tag1 NMTOKEN #IMPLIED > | |||||
| * <!-- Second tag --> | |||||
| * <!ATTLIST tagdiff tag2 NMTOKEN #IMPLIED > | |||||
| * <!-- Subversion BaseURL --> | |||||
| * <!ATTLIST tagdiff svnurl NMTOKEN #IMPLIED > | |||||
| * | |||||
| * <!-- 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="svntagdiff" | |||||
| */ | |||||
| public class SvnTagDiff extends AbstractSvnTask { | |||||
| /** | |||||
| * Used to create the temp file for svn log | |||||
| */ | |||||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||||
| /** | |||||
| * The earliest revision from which diffs are to be included in the report. | |||||
| */ | |||||
| private String tag1; | |||||
| /** | |||||
| * The latest revision from which diffs are to be included in the report. | |||||
| */ | |||||
| private String tag2; | |||||
| /** | |||||
| * The file in which to write the diff report. | |||||
| */ | |||||
| private File mydestfile; | |||||
| /** | |||||
| * Base URL. | |||||
| */ | |||||
| private String baseURL; | |||||
| /** | |||||
| * Set the first tag. | |||||
| * | |||||
| * @param s the first tag. | |||||
| */ | |||||
| public void setTag1(String s) { | |||||
| tag1 = s; | |||||
| } | |||||
| /** | |||||
| * Set the second tag. | |||||
| * | |||||
| * @param s the second tag. | |||||
| */ | |||||
| public void setTag2(String s) { | |||||
| tag2 = s; | |||||
| } | |||||
| /** | |||||
| * Set the output file for the diff. | |||||
| * | |||||
| * @param f the output file for the diff. | |||||
| */ | |||||
| public void setDestFile(File f) { | |||||
| mydestfile = f; | |||||
| } | |||||
| /** | |||||
| * Set the base URL from which to calculate tag URLs. | |||||
| * | |||||
| * @param u the base URL from which to calculate tag URLs. | |||||
| */ | |||||
| public void setBaseURL(String u) { | |||||
| baseURL = u; | |||||
| if (!u.endsWith("/")) { | |||||
| baseURL += "/"; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Execute task. | |||||
| * | |||||
| * @exception BuildException if an error occurs | |||||
| */ | |||||
| public void execute() throws BuildException { | |||||
| // validate the input parameters | |||||
| validate(); | |||||
| // build the rdiff command | |||||
| setSubCommand("diff"); | |||||
| addSubCommandArgument("--no-diff-deleted"); | |||||
| if (tag1.equals("trunk") || tag1.equals("trunk/")) { | |||||
| addSubCommandArgument(baseURL + "trunk/"); | |||||
| } else { | |||||
| if (tag1.endsWith("/")) { | |||||
| addSubCommandArgument(baseURL + "tags/" + tag1); | |||||
| } else { | |||||
| addSubCommandArgument(baseURL + "tags/" + tag1 + "/"); | |||||
| } | |||||
| } | |||||
| if (tag2 == null || tag2.equals("trunk") || tag2.equals("trunk/")) { | |||||
| addSubCommandArgument(baseURL + "trunk/"); | |||||
| } else { | |||||
| if (tag2.endsWith("/")) { | |||||
| addSubCommandArgument(baseURL + "tags/" + tag2); | |||||
| } else { | |||||
| addSubCommandArgument(baseURL + "tags/" + tag2 + "/"); | |||||
| } | |||||
| } | |||||
| File tmpFile = null; | |||||
| try { | |||||
| tmpFile = | |||||
| FILE_UTILS.createTempFile("svntagdiff", ".log", null); | |||||
| tmpFile.deleteOnExit(); | |||||
| setOutput(tmpFile); | |||||
| // run the svn command | |||||
| super.execute(); | |||||
| // parse the diff | |||||
| SvnEntry.Path[] entries = SvnDiffHandler.parseDiff(tmpFile); | |||||
| // write the revision diff | |||||
| SvnDiffHandler.writeDiff(mydestfile, entries, "tagdiff", | |||||
| "tag1", tag1, "tag2", | |||||
| tag2 == null ? "trunk" : tag2, | |||||
| baseURL); | |||||
| } finally { | |||||
| if (tmpFile != null) { | |||||
| tmpFile.delete(); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 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 == tag1) { | |||||
| throw new BuildException("tag1 must be set."); | |||||
| } | |||||
| if (null == baseURL) { | |||||
| throw new BuildException("baseURL must be set."); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -27,4 +27,8 @@ | |||||
| name="revisiondiff" | name="revisiondiff" | ||||
| classname="org.apache.tools.ant.taskdefs.svn.SvnRevisionDiff" | classname="org.apache.tools.ant.taskdefs.svn.SvnRevisionDiff" | ||||
| /> | /> | ||||
| <taskdef | |||||
| name="tagdiff" | |||||
| classname="org.apache.tools.ant.taskdefs.svn.SvnTagDiff" | |||||
| /> | |||||
| </antlib> | </antlib> | ||||
| @@ -74,9 +74,9 @@ public class SvnRevisionDiffTest extends BuildFileTest { | |||||
| int end = log.indexOf(">", start); | int end = log.indexOf(">", start); | ||||
| Assert.assertTrue(end > -1); | Assert.assertTrue(end > -1); | ||||
| Assert.assertTrue(log.indexOf("start=\"152904\"", start) > -1); | Assert.assertTrue(log.indexOf("start=\"152904\"", start) > -1); | ||||
| Assert.assertTrue(log.indexOf("start=\"152904\"") < end); | |||||
| Assert.assertTrue(log.indexOf("start=\"152904\"", start) < end); | |||||
| Assert.assertTrue(log.indexOf("end=\"153682\"", start) > -1); | Assert.assertTrue(log.indexOf("end=\"153682\"", start) > -1); | ||||
| Assert.assertTrue(log.indexOf("end=\"153682\"") < end); | |||||
| Assert.assertTrue(log.indexOf("end=\"153682\"", start) < end); | |||||
| } | } | ||||
| private static final void assertAttributesNoURL(String log) { | private static final void assertAttributesNoURL(String log) { | ||||
| @@ -0,0 +1,144 @@ | |||||
| /* | |||||
| * 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.IOException; | |||||
| import java.io.FileReader; | |||||
| import org.apache.tools.ant.BuildFileTest; | |||||
| import org.apache.tools.ant.util.FileUtils; | |||||
| import junit.framework.Assert; | |||||
| /** | |||||
| */ | |||||
| public class SvnTagDiffTest extends BuildFileTest { | |||||
| public SvnTagDiffTest(String name) { | |||||
| super(name); | |||||
| } | |||||
| public void setUp() { | |||||
| configureProject("src/etc/testcases/tagdiff.xml"); | |||||
| } | |||||
| public void tearDown() { | |||||
| executeTarget("cleanup"); | |||||
| } | |||||
| public void testDiffWithTwoTags() throws IOException { | |||||
| String log = executeTargetAndReadLogFully("diff-with-two-tags"); | |||||
| assertAttributes(log, "initial", "BCEL_5_0"); | |||||
| assertAdded1(log); | |||||
| } | |||||
| public void testDiffWithExplicitTrunk() throws IOException { | |||||
| String log = executeTargetAndReadLogFully("diff-with-explicit-trunk"); | |||||
| assertDiffWithTrunk(log); | |||||
| } | |||||
| public void testDiffWithImplicitTrunk() throws IOException { | |||||
| String log = executeTargetAndReadLogFully("diff-with-implicit-trunk"); | |||||
| assertDiffWithTrunk(log); | |||||
| } | |||||
| private static void assertDiffWithTrunk(String log) { | |||||
| assertAttributes(log, "BCEL_5_0", "trunk"); | |||||
| assertAdded(log); | |||||
| assertModified(log); | |||||
| assertDeleted(log); | |||||
| } | |||||
| private String executeTargetAndReadLogFully(String target) | |||||
| throws IOException { | |||||
| executeTarget(target); | |||||
| FileReader r = new FileReader(getProject() | |||||
| .resolveFile("tmpdir/diff.xml")); | |||||
| try { | |||||
| return FileUtils.readFully(r); | |||||
| } finally { | |||||
| r.close(); | |||||
| } | |||||
| } | |||||
| private static final void assertAttributes(String log, String tag1, | |||||
| String tag2) { | |||||
| int start = log.indexOf("<tagdiff"); | |||||
| Assert.assertTrue(start > -1); | |||||
| int end = log.indexOf(">", start); | |||||
| Assert.assertTrue(end > -1); | |||||
| Assert.assertTrue(log.indexOf("tag1=\"" + tag1 + "\"", start) > -1); | |||||
| Assert.assertTrue(log.indexOf("tag1=\"" + tag1 + "\"", start) < end); | |||||
| Assert.assertTrue(log.indexOf("tag2=\"" + tag2 + "\"", start) > -1); | |||||
| Assert.assertTrue(log.indexOf("tag2=\"" + tag2 + "\"", start) < end); | |||||
| Assert.assertTrue(log.indexOf("svnurl=\"http://svn.apache.org/repos/" | |||||
| + "asf/jakarta/bcel/\"", start) > -1); | |||||
| Assert.assertTrue(log.indexOf("svnurl=\"http://svn.apache.org/repos/" | |||||
| + "asf/jakarta/bcel/\"", start) < end); | |||||
| } | |||||
| private static final void assertAdded(String log) { | |||||
| int name = log.indexOf("<![CDATA[LICENSE.txt]]>"); | |||||
| Assert.assertTrue(name > -1); | |||||
| int pathAfterName = log.indexOf("</path>", name); | |||||
| Assert.assertTrue(pathAfterName > -1); | |||||
| Assert.assertTrue(log.indexOf("<action>added</action>", name) > -1); | |||||
| Assert.assertTrue(log.indexOf("<action>added</action>", name) | |||||
| < pathAfterName); | |||||
| } | |||||
| private static final void assertModified(String log) { | |||||
| int name = log.indexOf("<name><![CDATA[src/java/org/apache/bcel/" | |||||
| + "Repository.java]]></name>"); | |||||
| Assert.assertTrue(name > -1); | |||||
| int pathAfterName = log.indexOf("</path>", name); | |||||
| Assert.assertTrue(pathAfterName > -1); | |||||
| Assert.assertTrue(log.indexOf("<action>modified</action>", name) > -1); | |||||
| Assert.assertTrue(log.indexOf("<action>modified</action>", name) | |||||
| < pathAfterName); | |||||
| } | |||||
| private static final void assertDeleted(String log) { | |||||
| int name = log.indexOf("<name><![CDATA[LICENSE]]></name>"); | |||||
| Assert.assertTrue(name > -1); | |||||
| int pathAfterName = log.indexOf("</path>", name); | |||||
| Assert.assertTrue(pathAfterName > -1); | |||||
| Assert.assertTrue(log.indexOf("<action>deleted</action>", name) > -1); | |||||
| Assert.assertTrue(log.indexOf("<action>deleted</action>", name) | |||||
| < pathAfterName); | |||||
| } | |||||
| private static final void assertAdded1(String log) { | |||||
| int name = log.indexOf("<name><![CDATA[src/java/org/apache/bcel/" | |||||
| + "Repository.java]]></name>"); | |||||
| Assert.assertTrue(name > -1); | |||||
| int pathAfterName = log.indexOf("</path>", name); | |||||
| Assert.assertTrue(pathAfterName > -1); | |||||
| Assert.assertTrue(log.indexOf("<action>added</action>", name) > -1); | |||||
| Assert.assertTrue(log.indexOf("<action>added</action>", name) | |||||
| < pathAfterName); | |||||
| } | |||||
| } | |||||