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. | |||
| 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 | |||
| ============================================= | |||
| @@ -125,6 +125,13 @@ operation may fail when using such an incompatible client. | |||
| included in the report.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </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> | |||
| <h3>Parameters specified as nested elements</h3> | |||
| @@ -22,8 +22,12 @@ import java.text.SimpleDateFormat; | |||
| import java.util.Date; | |||
| import java.util.Enumeration; | |||
| import java.util.Hashtable; | |||
| import java.util.Iterator; | |||
| import java.util.List; | |||
| import java.util.Locale; | |||
| 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. | |||
| @@ -67,6 +71,30 @@ class ChangeLogParser { | |||
| /** rcs entries */ | |||
| 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. | |||
| * | |||
| @@ -148,11 +176,29 @@ class ChangeLogParser { | |||
| * @param line the line to process | |||
| */ | |||
| private void processFile(final String line) { | |||
| if (line.startsWith("Working file:")) { | |||
| if (!remote && line.startsWith("Working file:")) { | |||
| // CheckStyle:MagicNumber OFF | |||
| file = line.substring(14, line.length()); | |||
| // CheckStyle:MagicNumber ON | |||
| 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. */ | |||
| 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 | |||
| * performed. If empty then all files in the working directory will | |||
| @@ -177,6 +181,15 @@ public class ChangeLogTask extends AbstractCvsTask { | |||
| 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. | |||
| @@ -210,6 +223,7 @@ public class ChangeLogTask extends AbstractCvsTask { | |||
| userList.put(user.getUserID(), user.getDisplayname()); | |||
| } | |||
| if (!remote) { | |||
| setCommand("log"); | |||
| if (getTag() != null) { | |||
| @@ -225,6 +239,17 @@ public class ChangeLogTask extends AbstractCvsTask { | |||
| 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) { | |||
| final SimpleDateFormat outputDate = | |||
| 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 = | |||
| new RedirectingStreamHandler(parser); | |||
| @@ -17,12 +17,15 @@ | |||
| */ | |||
| package org.apache.tools.ant.util; | |||
| import java.util.ArrayList; | |||
| import java.util.Collection; | |||
| import java.util.Vector; | |||
| import java.util.Iterator; | |||
| import java.util.Collections; | |||
| import java.util.Dictionary; | |||
| import java.util.Enumeration; | |||
| import java.util.Iterator; | |||
| import java.util.List; | |||
| import java.util.NoSuchElementException; | |||
| import java.util.Vector; | |||
| // CheckStyle:HideUtilityClassConstructorCheck OFF - bc | |||
| @@ -33,6 +36,12 @@ import java.util.NoSuchElementException; | |||
| */ | |||
| 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(). | |||
| * @param v1 the first vector. | |||
| @@ -38,6 +38,28 @@ | |||
| <au:assertFileExists file="${output}/report.xml"/> | |||
| </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"> | |||
| <mkdir dir="${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 | |||
| O48f80ad6|stefan|/tmp/testoutput/*0|ant module 2||ant module 2 | |||
| 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 | |||