git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277668 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -0,0 +1,129 @@ | |||
| <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> | |||
| @@ -0,0 +1,140 @@ | |||
| <!-- | |||
| 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> | |||
| @@ -0,0 +1,60 @@ | |||
| <?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> | |||
| @@ -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; | |||
| } | |||
| @@ -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. | |||
| * <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."); | |||
| } | |||
| } | |||
| } | |||
| @@ -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> | |||