From 80d45d8dbdc9cd56b35dfdd702e779429cead4e4 Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Fri, 17 Oct 2008 15:16:28 +0000 Subject: [PATCH] add remote option to use rlog instead of log to cvschangelog. Submitted by Rob van Oostrum. PR 27419. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@705639 13f79535-47bb-0310-9956-ffa450edef68 --- WHATSNEW | 4 ++ docs/manual/CoreTasks/changelog.html | 7 +++ .../ant/taskdefs/cvslib/ChangeLogParser.java | 48 ++++++++++++++++++- .../ant/taskdefs/cvslib/ChangeLogTask.java | 29 ++++++++++- .../tools/ant/util/CollectionUtils.java | 13 ++++- src/tests/antunit/taskdefs/cvs/cvs.xml | 22 +++++++++ .../taskdefs/cvs/repository/CVSROOT/history | 8 ++++ 7 files changed, 127 insertions(+), 4 deletions(-) diff --git a/WHATSNEW b/WHATSNEW index 8fcff2988..95e37f75f 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -469,6 +469,10 @@ Other changes: behavior of Ant 1.7.0. Bugzilla Report 46010. + * If the new remote attribute is set to true, 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 ============================================= diff --git a/docs/manual/CoreTasks/changelog.html b/docs/manual/CoreTasks/changelog.html index b36c58dda..d90aa3c27 100644 --- a/docs/manual/CoreTasks/changelog.html +++ b/docs/manual/CoreTasks/changelog.html @@ -125,6 +125,13 @@ operation may fail when using such an incompatible client. included in the report. No + + remote + If set to true, works against the repository + (using rlog) without a working copy. Default is + false. Since Ant 1.8.0 + No +

Parameters specified as nested elements

diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParser.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParser.java index a1f0336fc..9fbe5f7a9 100644 --- a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParser.java +++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParser.java @@ -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; } } diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java index e8290905b..cef90f299 100644 --- a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java @@ -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); diff --git a/src/main/org/apache/tools/ant/util/CollectionUtils.java b/src/main/org/apache/tools/ant/util/CollectionUtils.java index bb5be8ca6..9195d2658 100644 --- a/src/main/org/apache/tools/ant/util/CollectionUtils.java +++ b/src/main/org/apache/tools/ant/util/CollectionUtils.java @@ -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. diff --git a/src/tests/antunit/taskdefs/cvs/cvs.xml b/src/tests/antunit/taskdefs/cvs/cvs.xml index aca5810db..d7184faef 100644 --- a/src/tests/antunit/taskdefs/cvs/cvs.xml +++ b/src/tests/antunit/taskdefs/cvs/cvs.xml @@ -38,6 +38,28 @@ + + + + + + + + + + + + + + + + diff --git a/src/tests/antunit/taskdefs/cvs/repository/CVSROOT/history b/src/tests/antunit/taskdefs/cvs/repository/CVSROOT/history index 8c9f1c5d2..a464ae678 100644 --- a/src/tests/antunit/taskdefs/cvs/repository/CVSROOT/history +++ b/src/tests/antunit/taskdefs/cvs/repository/CVSROOT/history @@ -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