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 |