git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@705639 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -469,6 +469,10 @@ Other changes: | |||||
| behavior of Ant 1.7.0. | behavior of Ant 1.7.0. | ||||
| Bugzilla Report 46010. | Bugzilla Report 46010. | ||||
| * If the new remote attribute is set to true, <cvschangelog> can now | |||||
| work against a remote repository without any working copy. | |||||
| Bugzilla Report 27419. | |||||
| Changes from Ant 1.7.0 TO Ant 1.7.1 | Changes from Ant 1.7.0 TO Ant 1.7.1 | ||||
| ============================================= | ============================================= | ||||
| @@ -125,6 +125,13 @@ operation may fail when using such an incompatible client. | |||||
| included in the report.</td> | included in the report.</td> | ||||
| <td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
| </tr> | </tr> | ||||
| <tr> | |||||
| <td valign="top">remote</td> | |||||
| <td valign="top">If set to true, works against the repository | |||||
| (using rlog) without a working copy. Default is | |||||
| false. <em>Since Ant 1.8.0</em></td> | |||||
| <td align="center" valign="top">No</td> | |||||
| </tr> | |||||
| </table> | </table> | ||||
| <h3>Parameters specified as nested elements</h3> | <h3>Parameters specified as nested elements</h3> | ||||
| @@ -22,8 +22,12 @@ import java.text.SimpleDateFormat; | |||||
| import java.util.Date; | import java.util.Date; | ||||
| import java.util.Enumeration; | import java.util.Enumeration; | ||||
| import java.util.Hashtable; | import java.util.Hashtable; | ||||
| import java.util.Iterator; | |||||
| import java.util.List; | |||||
| import java.util.Locale; | import java.util.Locale; | ||||
| import java.util.TimeZone; | import java.util.TimeZone; | ||||
| import org.apache.tools.ant.taskdefs.AbstractCvsTask; | |||||
| import org.apache.tools.ant.util.CollectionUtils; | |||||
| /** | /** | ||||
| * A class used to parse the output of the CVS log command. | * A class used to parse the output of the CVS log command. | ||||
| @@ -67,6 +71,30 @@ class ChangeLogParser { | |||||
| /** rcs entries */ | /** rcs entries */ | ||||
| private final Hashtable entries = new Hashtable(); | private final Hashtable entries = new Hashtable(); | ||||
| private final boolean remote; | |||||
| private final String[] moduleNames; | |||||
| private final int[] moduleNameLengths; | |||||
| public ChangeLogParser() { | |||||
| this(false, "", CollectionUtils.EMPTY_LIST); | |||||
| } | |||||
| public ChangeLogParser(boolean remote, String packageName, List modules) { | |||||
| this.remote = remote; | |||||
| moduleNames = new String[modules.size() + (packageName == null ? 0 : 1)]; | |||||
| moduleNameLengths = new int[moduleNames.length]; | |||||
| int i = 0; | |||||
| if (packageName != null) { | |||||
| moduleNames[i] = packageName; | |||||
| moduleNameLengths[i++] = packageName.length(); | |||||
| } | |||||
| for (Iterator iter = modules.iterator(); iter.hasNext(); i++) { | |||||
| AbstractCvsTask.Module m = (AbstractCvsTask.Module) iter.next(); | |||||
| moduleNames[i] = m.getName(); | |||||
| moduleNameLengths[i] = moduleNames[i].length(); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Get a list of rcs entries as an array. | * Get a list of rcs entries as an array. | ||||
| * | * | ||||
| @@ -148,11 +176,29 @@ class ChangeLogParser { | |||||
| * @param line the line to process | * @param line the line to process | ||||
| */ | */ | ||||
| private void processFile(final String line) { | private void processFile(final String line) { | ||||
| if (line.startsWith("Working file:")) { | |||||
| if (!remote && line.startsWith("Working file:")) { | |||||
| // CheckStyle:MagicNumber OFF | // CheckStyle:MagicNumber OFF | ||||
| file = line.substring(14, line.length()); | file = line.substring(14, line.length()); | ||||
| // CheckStyle:MagicNumber ON | // CheckStyle:MagicNumber ON | ||||
| status = GET_REVISION; | status = GET_REVISION; | ||||
| } else if (remote && line.startsWith("RCS file:")) { | |||||
| // exclude the part of the RCS filename up to and | |||||
| // including the module name (and the path separator) | |||||
| int startOfFileName = 0; | |||||
| for (int i = 0; i < moduleNames.length; i++) { | |||||
| int index = line.indexOf(moduleNames[i]); | |||||
| if (index >= 0) { | |||||
| startOfFileName = index + moduleNameLengths[i] + 1; | |||||
| break; | |||||
| } | |||||
| } | |||||
| int endOfFileName = line.indexOf(",v"); | |||||
| if (endOfFileName == -1) { | |||||
| file = line.substring(startOfFileName); | |||||
| } else { | |||||
| file = line.substring(startOfFileName, endOfFileName); | |||||
| } | |||||
| status = GET_REVISION; | |||||
| } | } | ||||
| } | } | ||||
| @@ -95,6 +95,10 @@ public class ChangeLogTask extends AbstractCvsTask { | |||||
| /** The latest date at which to stop processing entries. */ | /** The latest date at which to stop processing entries. */ | ||||
| private Date endDate; | private Date endDate; | ||||
| /** Determines whether log (false) or rlog (true) is used */ | |||||
| private boolean remote = false; | |||||
| /** | /** | ||||
| * Filesets containing list of files against which the cvs log will be | * Filesets containing list of files against which the cvs log will be | ||||
| * performed. If empty then all files in the working directory will | * performed. If empty then all files in the working directory will | ||||
| @@ -177,6 +181,15 @@ public class ChangeLogTask extends AbstractCvsTask { | |||||
| setStart(new Date(time)); | setStart(new Date(time)); | ||||
| } | } | ||||
| /** | |||||
| * Whether to use rlog against a remote repository instead of log | |||||
| * in a working copy's directory. | |||||
| * | |||||
| * @since Ant 1.8.0 | |||||
| */ | |||||
| public void setRemote(final boolean remote) { | |||||
| this.remote = remote; | |||||
| } | |||||
| /** | /** | ||||
| * Adds a set of files about which cvs logs will be generated. | * Adds a set of files about which cvs logs will be generated. | ||||
| @@ -210,6 +223,7 @@ public class ChangeLogTask extends AbstractCvsTask { | |||||
| userList.put(user.getUserID(), user.getDisplayname()); | userList.put(user.getUserID(), user.getDisplayname()); | ||||
| } | } | ||||
| if (!remote) { | |||||
| setCommand("log"); | setCommand("log"); | ||||
| if (getTag() != null) { | if (getTag() != null) { | ||||
| @@ -225,6 +239,17 @@ public class ChangeLogTask extends AbstractCvsTask { | |||||
| addCommandArgument("-S"); | addCommandArgument("-S"); | ||||
| } | } | ||||
| } | } | ||||
| } else { | |||||
| // supply 'rlog' as argument instead of command | |||||
| setCommand(""); | |||||
| addCommandArgument("rlog"); | |||||
| // Do not print name/header if no revisions | |||||
| // selected. This is quicker: less output to parse. | |||||
| addCommandArgument("-S"); | |||||
| // Do not list tags. This is quicker: less output to | |||||
| // parse. | |||||
| addCommandArgument("-N"); | |||||
| } | |||||
| if (null != startDate) { | if (null != startDate) { | ||||
| final SimpleDateFormat outputDate = | final SimpleDateFormat outputDate = | ||||
| new SimpleDateFormat("yyyy-MM-dd"); | new SimpleDateFormat("yyyy-MM-dd"); | ||||
| @@ -253,7 +278,9 @@ public class ChangeLogTask extends AbstractCvsTask { | |||||
| } | } | ||||
| } | } | ||||
| final ChangeLogParser parser = new ChangeLogParser(); | |||||
| final ChangeLogParser parser = new ChangeLogParser(remote, | |||||
| getPackage(), | |||||
| getModules()); | |||||
| final RedirectingStreamHandler handler = | final RedirectingStreamHandler handler = | ||||
| new RedirectingStreamHandler(parser); | new RedirectingStreamHandler(parser); | ||||
| @@ -17,12 +17,15 @@ | |||||
| */ | */ | ||||
| package org.apache.tools.ant.util; | package org.apache.tools.ant.util; | ||||
| import java.util.ArrayList; | |||||
| import java.util.Collection; | import java.util.Collection; | ||||
| import java.util.Vector; | |||||
| import java.util.Iterator; | |||||
| import java.util.Collections; | |||||
| import java.util.Dictionary; | import java.util.Dictionary; | ||||
| import java.util.Enumeration; | import java.util.Enumeration; | ||||
| import java.util.Iterator; | |||||
| import java.util.List; | |||||
| import java.util.NoSuchElementException; | import java.util.NoSuchElementException; | ||||
| import java.util.Vector; | |||||
| // CheckStyle:HideUtilityClassConstructorCheck OFF - bc | // CheckStyle:HideUtilityClassConstructorCheck OFF - bc | ||||
| @@ -33,6 +36,12 @@ import java.util.NoSuchElementException; | |||||
| */ | */ | ||||
| public class CollectionUtils { | public class CollectionUtils { | ||||
| /** | |||||
| * Collections.emptyList() is Java5+. | |||||
| */ | |||||
| public static final List EMPTY_LIST = | |||||
| Collections.unmodifiableList(new ArrayList(0)); | |||||
| /** | /** | ||||
| * Please use Vector.equals() or List.equals(). | * Please use Vector.equals() or List.equals(). | ||||
| * @param v1 the first vector. | * @param v1 the first vector. | ||||
| @@ -38,6 +38,28 @@ | |||||
| <au:assertFileExists file="${output}/report.xml"/> | <au:assertFileExists file="${output}/report.xml"/> | ||||
| </target> | </target> | ||||
| <target name="testRemoteChangelog"> | |||||
| <mkdir dir="${output}"/> | |||||
| <cvschangelog cvsroot="${cvsroot}" package="antmodule3" | |||||
| remote="true" | |||||
| destfile="${output}/report.xml"/> | |||||
| <au:assertFileExists file="${output}/report.xml"/> | |||||
| <au:assertResourceContains resource="${output}/report.xml" | |||||
| value="[yet another test.txt]"/> | |||||
| </target> | |||||
| <target name="testRemoteChangelogNestedModule"> | |||||
| <mkdir dir="${output}"/> | |||||
| <cvschangelog cvsroot="${cvsroot}" | |||||
| remote="true" | |||||
| destfile="${output}/report.xml"> | |||||
| <module name="antmodule3"/> | |||||
| </cvschangelog> | |||||
| <au:assertFileExists file="${output}/report.xml"/> | |||||
| <au:assertResourceContains resource="${output}/report.xml" | |||||
| value="[yet another test.txt]"/> | |||||
| </target> | |||||
| <target name="testCvsWithSpaceInModule"> | <target name="testCvsWithSpaceInModule"> | ||||
| <mkdir dir="${output}"/> | <mkdir dir="${output}"/> | ||||
| <cvs cvsroot="${cvsroot}" dest="${output}"> | <cvs cvsroot="${cvsroot}" dest="${output}"> | ||||
| @@ -20,3 +20,11 @@ O48f80394|stefan|/tmp/testoutput/*0|ant module 2||ant module 2 | |||||
| O48f80395|stefan|/tmp/testoutput/*0|antmodule1||antmodule1 | O48f80395|stefan|/tmp/testoutput/*0|antmodule1||antmodule1 | ||||
| O48f80ad6|stefan|/tmp/testoutput/*0|ant module 2||ant module 2 | O48f80ad6|stefan|/tmp/testoutput/*0|ant module 2||ant module 2 | ||||
| O48f80ad7|stefan|/tmp/testoutput/*0|antmodule1||antmodule1 | O48f80ad7|stefan|/tmp/testoutput/*0|antmodule1||antmodule1 | ||||
| O48f8a1d1|stefan|/tmp/testoutput/*0|ant module 2||ant module 2 | |||||
| O48f8a1d2|stefan|/tmp/testoutput/*0|antmodule1||antmodule1 | |||||
| O48f8a6a4|stefan|/tmp/testoutput/*0|ant module 2||ant module 2 | |||||
| O48f8a6a6|stefan|/tmp/testoutput/*0|antmodule1||antmodule1 | |||||
| O48f8a764|stefan|/tmp/testoutput/*0|ant module 2||ant module 2 | |||||
| O48f8a766|stefan|/tmp/testoutput/*0|antmodule1||antmodule1 | |||||
| O48f8abf0|stefan|/tmp/testoutput/*0|ant module 2||ant module 2 | |||||
| O48f8abf2|stefan|/tmp/testoutput/*0|antmodule1||antmodule1 | |||||