From e847b7051b2d5bff53a801a32df9f95f73d11f0e Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Mon, 14 Feb 2005 13:28:33 +0000 Subject: [PATCH] svnchangelog task, very similar to cvschangelog - has a lot of potential for improvements git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277653 13f79535-47bb-0310-9956-ffa450edef68 --- proposal/sandbox/svn/README | 6 - .../svn/src/etc/testcases/changelog.xml | 61 +++ .../ant/taskdefs/svn/AbstractSvnTask.java | 18 +- .../svn/LineOrientedOutputStream.java | 134 ++++++ .../ant/taskdefs/svn/SvnChangeLogParser.java | 188 +++++++++ .../ant/taskdefs/svn/SvnChangeLogTask.java | 398 ++++++++++++++++++ .../ant/taskdefs/svn/SvnChangeLogWriter.java | 81 ++++ .../tools/ant/taskdefs/svn/SvnEntry.java | 115 +++++ .../apache/tools/ant/taskdefs/svn/antlib.xml | 4 + 9 files changed, 998 insertions(+), 7 deletions(-) create mode 100644 proposal/sandbox/svn/src/etc/testcases/changelog.xml create mode 100644 proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/LineOrientedOutputStream.java create mode 100644 proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogParser.java create mode 100644 proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogTask.java create mode 100644 proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogWriter.java create mode 100644 proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java diff --git a/proposal/sandbox/svn/README b/proposal/sandbox/svn/README index a689336cf..0887c166c 100644 --- a/proposal/sandbox/svn/README +++ b/proposal/sandbox/svn/README @@ -18,9 +18,3 @@ SVN, matching what the traditional Ant task(s) vor CVS could do. If you need more than what this libary provides, we encourage you to check out the existing alternatives. -=============== - -The first cut will mimic the implementation of the task, it will -even be split into an abstract task and a very thin real task - it may -be possible to base tasks similar to the optional CVS tasks on the -abstract task as well. diff --git a/proposal/sandbox/svn/src/etc/testcases/changelog.xml b/proposal/sandbox/svn/src/etc/testcases/changelog.xml new file mode 100644 index 000000000..3dac0d9e6 --- /dev/null +++ b/proposal/sandbox/svn/src/etc/testcases/changelog.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/AbstractSvnTask.java b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/AbstractSvnTask.java index 1ffd65030..d40976f02 100644 --- a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/AbstractSvnTask.java +++ b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/AbstractSvnTask.java @@ -69,6 +69,11 @@ public abstract class AbstractSvnTask extends Task { */ private boolean quiet = false; + /** + * be verbose + */ + private boolean verbose = false; + /** * report only, don't change any files. */ @@ -466,6 +471,14 @@ public abstract class AbstractSvnTask extends Task { quiet = q; } + /** + * If true, be verbose. + * @param q if true, be verbose. + */ + public void setVerbose(boolean v) { + verbose = v; + } + /** * If true, report only and don't change any files. * @@ -523,7 +536,7 @@ public abstract class AbstractSvnTask extends Task { *
  • * quiet *
  • - *
  • svnroot
  • + *
  • verbose
  • *
  • dryrun
  • * */ @@ -535,6 +548,9 @@ public abstract class AbstractSvnTask extends Task { if (quiet) { c.createArgument(true).setValue("--quiet"); } + if (verbose) { + c.createArgument(true).setValue("--verbose"); + } if (dryrun) { c.createArgument(true).setValue("--dry-run"); } diff --git a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/LineOrientedOutputStream.java b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/LineOrientedOutputStream.java new file mode 100644 index 000000000..e15d9db53 --- /dev/null +++ b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/LineOrientedOutputStream.java @@ -0,0 +1,134 @@ +/* + * 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.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Invokes {@link #processLine processLine} whenever a full line has + * been written to this stream. + * + *

    Tries to be smart about line separators.

    + */ +public abstract class LineOrientedOutputStream extends OutputStream { + + /** Initial buffer size. */ + private static final int INTIAL_SIZE = 132; + + /** Carriage return */ + private static final int CR = 0x0d; + + /** Linefeed */ + private static final int LF = 0x0a; + + private ByteArrayOutputStream buffer + = new ByteArrayOutputStream(INTIAL_SIZE); + private boolean skip = false; + + /** + * Write the data to the buffer and flush the buffer, if a line + * separator is detected. + * + * @param cc data to log (byte). + */ + public final void write(int cc) throws IOException { + final byte c = (byte) cc; + if ((c == '\n') || (c == '\r')) { + if (!skip) { + processBuffer(); + } + } else { + buffer.write(cc); + } + skip = (c == '\r'); + } + + /** + * Flush this log stream + */ + public final void flush() throws IOException { + if (buffer.size() > 0) { + processBuffer(); + } + } + + /** + * Converts the buffer to a string and sends it to + * processLine + */ + private void processBuffer() throws IOException { + try { + processLine(buffer.toString()); + } finally { + buffer.reset(); + } + } + + /** + * Processes a line. + * + * @param line the line to log. + */ + protected abstract void processLine(String line) throws IOException; + + /** + * Writes all remaining + */ + public final void close() throws IOException { + if (buffer.size() > 0) { + processBuffer(); + } + super.close(); + } + + /** + * Write a block of characters to the output stream + * + * @param b the array containing the data + * @param off the offset into the array where data starts + * @param len the length of block + * + * @throws IOException if the data cannot be written into the stream. + */ + public final void write(byte[] b, int off, int len) throws IOException { + // find the line breaks and pass other chars through in blocks + int offset = off; + int blockStartOffset = offset; + int remaining = len; + while (remaining > 0) { + while (remaining > 0 && b[offset] != LF && b[offset] != CR) { + offset++; + remaining--; + } + // either end of buffer or a line separator char + int blockLength = offset - blockStartOffset; + if (blockLength > 0) { + buffer.write(b, blockStartOffset, blockLength); + } + while (remaining > 0 && (b[offset] == LF || b[offset] == CR)) { + write(b[offset]); + offset++; + remaining--; + } + blockStartOffset = offset; + } + } + +} diff --git a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogParser.java b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogParser.java new file mode 100644 index 000000000..ba20d5725 --- /dev/null +++ b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogParser.java @@ -0,0 +1,188 @@ +/* + * 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.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.ArrayList; + +/** + * A class used to parse the output of the svn log command. + * + * @version $Revision$ $Date$ + */ +class SvnChangeLogParser extends LineOrientedOutputStream { + + private final static int GET_ENTRY_LINE = 0; + private final static int GET_REVISION_LINE = 1; + private final static int GET_PATHS = 2; + private final static int GET_MESSAGE = 3; + + private String message = ""; + private Date date = null; + private String author = null; + private String revision = null; + private ArrayList paths = new ArrayList(); + + /** input format for dates read in from cvs log */ + private static final String PATTERN = "yyyy-MM-dd HH:mm:ss"; + private static final SimpleDateFormat INPUT_DATE + = new SimpleDateFormat(PATTERN); + + private final ArrayList entries = new ArrayList(); + private int status = GET_ENTRY_LINE; + + /** + * Get a list of rcs entries as an array. + * + * @return a list of rcs entries as an array + */ + public SvnEntry[] getEntrySetAsArray() { + return (SvnEntry[]) entries.toArray(new SvnEntry[entries.size()]); + } + + /** + * Receive notification about the process writing + * to standard output. + * @param line the line to process + */ + public void processLine(final String line) { + switch(status) { + case GET_ENTRY_LINE: + // make sure attributes are reset when + // working on a 'new' file. + reset(); + processEntryStart(line); + break; + case GET_REVISION_LINE: + processRevision(line); + break; + + case GET_MESSAGE: + processMessage(line); + break; + + case GET_PATHS: + processPath(line); + break; + + default: + // Do nothing + break; + } + } + + /** + * Process a line while in "GET_MESSAGE" state. + * + * @param line the line + */ + private void processMessage(final String line) { + final String lineSeparator = System.getProperty("line.separator"); + if (line.equals("------------------------------------------------------------------------")) { + //We have ended changelog for that particular revision + //so we can save it + final int end + = message.length() - lineSeparator.length(); //was -1 + message = message.substring(0, end); + saveEntry(); + status = GET_REVISION_LINE; + } else { + message += line + lineSeparator; + } + } + + /** + * Process a line while in "GET_ENTRY_LINE" state. + * + * @param line the line to process + */ + private void processEntryStart(final String line) { + if (line.equals("------------------------------------------------------------------------")) { + status = GET_REVISION_LINE; + } + } + + /** + * Process a line while in "REVISION" state. + * + * @param line the line to process + */ + private void processRevision(final String line) { + int index = line.indexOf(" |"); + if (line.startsWith("r") + && (line.endsWith("lines") || line.endsWith("line")) + && index > -1) { + revision = line.substring(1, index); + int end = line.indexOf(" |", index + 1); + author = line.substring(index + 3, end); + String d = line.substring(end + 3, end + 3 + PATTERN.length()); + date = parseDate(d); + status = GET_PATHS; + } + } + + /** + * Process a line while in "GET_PATHS" state. + * + * @param line the line to process + */ + private void processPath(final String line) { + if (line.startsWith("Changed paths:")) { + // ignore + } else if (line.equals("")) { + status = GET_MESSAGE; + } else { + paths.add(line.substring(5)); + } + } + + /** + * Utility method that saves the current entry. + */ + private void saveEntry() { + SvnEntry entry = new SvnEntry(date, revision, author, message, + paths); + entries.add(entry); + } + + /** + * Parse date out from expected format. + * + * @param date the string holding date + * @return the date object or null if unknown date format + */ + private Date parseDate(final String date) { + try { + return INPUT_DATE.parse(date); + } catch (ParseException e) { + return null; + } + } + + /** + * Reset all internal attributes except status. + */ + public void reset() { + this.date = null; + this.author = null; + this.message = ""; + this.revision = null; + this.paths.clear(); + } +} diff --git a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogTask.java b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogTask.java new file mode 100644 index 000000000..26f3dea9b --- /dev/null +++ b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogTask.java @@ -0,0 +1,398 @@ +/* + * 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.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Enumeration; +import java.util.Properties; +import java.util.Vector; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.LogOutputStream; +import org.apache.tools.ant.taskdefs.PumpStreamHandler; +import org.apache.tools.ant.taskdefs.cvslib.CvsUser; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.util.FileUtils; + +/** + * Examines the output of svn log and group related changes together. + * + * It produces an XML output representing the list of changes. + *
    + * <!-- Root element -->
    + * <!ELEMENT changelog (entry+)>
    + * <!-- SVN Entry -->
    + * <!ELEMENT entry (date,time,revision,author,file+,msg,msg)>
    + * <!-- Date of svn entry -->
    + * <!ELEMENT date (#PCDATA)>
    + * <!-- Time of svn entry -->
    + * <!ELEMENT time (#PCDATA)>
    + * <!-- Author of change -->
    + * <!ELEMENT author (#PCDATA)>
    + * <!-- commit message -->
    + * <!ELEMENT msg (#PCDATA)>
    + * <!-- List of files affected -->
    + * <!ELEMENT file (name?)>
    + * <!-- Name of the file -->
    + * <!ELEMENT name (#PCDATA)>
    + * <!-- Revision number -->
    + * <!ELEMENT revision (#PCDATA)>
    + * 
    + * + * @ant.task name="svnchangelog" category="scm" + */ +public class SvnChangeLogTask extends AbstractSvnTask { + /** User list */ + private File usersFile; + + /** User list */ + private Vector svnUsers = new Vector(); + + /** Input dir */ + private File inputDir; + + /** Output file */ + private File destFile; + + /** The earliest revision at which to start processing entries. */ + private String startRevision; + + /** The latest revision at which to stop processing entries. */ + private String endRevision; + + /** + * Filesets containing list of files against which the svn log will be + * performed. If empty then all files in the working directory will + * be checked. + */ + private final Vector filesets = new Vector(); + + + /** + * Set the base dir for svn. + * + * @param inputDir The new dir value + */ + public void setDir(final File inputDir) { + this.inputDir = inputDir; + } + + + /** + * Set the output file for the log. + * + * @param destFile The new destfile value + */ + public void setDestfile(final File destFile) { + this.destFile = destFile; + } + + + /** + * Set a lookup list of user names & addresses + * + * @param usersFile The file containing the users info. + */ + public void setUsersfile(final File usersFile) { + this.usersFile = usersFile; + } + + + /** + * Add a user to list changelog knows about. + * + * @param user the user + */ + public void addUser(final CvsUser user) { + svnUsers.addElement(user); + } + + + /** + * Set the revision at which the changelog should start. + * + * @param start The revision at which the changelog should start. + */ + public void setStart(final String start) { + this.startRevision = start; + } + + + /** + * Set the revision at which the changelog should stop. + * + * @param endRevision The revision at which the changelog should stop. + */ + public void setEnd(final String endRevision) { + this.endRevision = endRevision; + } + + + /** + * Set the number of days worth of log entries to process. + * + * @param days the number of days of log to process. + */ + public void setDaysinpast(final int days) { + final long time = System.currentTimeMillis() + - (long) days * 24 * 60 * 60 * 1000; + + final SimpleDateFormat outputDate = + new SimpleDateFormat("{yyyy-MM-dd}"); + setStart(outputDate.format(new Date(time))); + } + + + /** + * Adds a set of files about which svn logs will be generated. + * + * @param fileSet a set of files about which svn logs will be generated. + */ + public void addFileset(final FileSet fileSet) { + filesets.addElement(fileSet); + } + + + /** + * Execute task + * + * @exception BuildException if something goes wrong executing the + * svn command + */ + public void execute() throws BuildException { + File savedDir = inputDir; // may be altered in validate + + try { + + validate(); + final Properties userList = new Properties(); + + loadUserlist(userList); + + for (int i = 0, size = svnUsers.size(); i < size; i++) { + final CvsUser user = (CvsUser) svnUsers.get(i); + user.validate(); + userList.put(user.getUserID(), user.getDisplayname()); + } + + setSubCommand("log"); + setVerbose(true); + + if (null != startRevision) { + if (null != endRevision) { + setRevision(startRevision + ":" + endRevision); + } else { + setRevision(startRevision + ":HEAD"); + } + } + + // Check if list of files to check has been specified + if (!filesets.isEmpty()) { + final Enumeration e = filesets.elements(); + + while (e.hasMoreElements()) { + final FileSet fileSet = (FileSet) e.nextElement(); + final DirectoryScanner scanner = + fileSet.getDirectoryScanner(getProject()); + final String[] files = scanner.getIncludedFiles(); + + for (int i = 0; i < files.length; i++) { + addSubCommandArgument(files[i]); + } + } + } + + final SvnChangeLogParser parser = new SvnChangeLogParser(); + final PumpStreamHandler handler = + new PumpStreamHandler(parser, + new LogOutputStream(this, + Project.MSG_ERR)); + + log(getSubCommand(), Project.MSG_VERBOSE); + + setDest(inputDir); + setExecuteStreamHandler(handler); + super.execute(); + + final SvnEntry[] entrySet = parser.getEntrySetAsArray(); + final SvnEntry[] filteredEntrySet = filterEntrySet(entrySet); + + replaceAuthorIdWithName(userList, filteredEntrySet); + + writeChangeLog(filteredEntrySet); + + } finally { + inputDir = savedDir; + } + } + + /** + * Validate the parameters specified for task. + * + * @throws BuildException if fails validation checks + */ + private void validate() + throws BuildException { + if (null == inputDir) { + inputDir = getDest(); + } + if (null == destFile) { + final String message = "Destfile must be set."; + + throw new BuildException(message); + } + if (!inputDir.exists()) { + final String message = "Cannot find base dir " + + inputDir.getAbsolutePath(); + + throw new BuildException(message); + } + if (null != usersFile && !usersFile.exists()) { + final String message = "Cannot find user lookup list " + + usersFile.getAbsolutePath(); + + throw new BuildException(message); + } + } + + /** + * Load the userlist from the userList file (if specified) and add to + * list of users. + * + * @param userList the file of users + * @throws BuildException if file can not be loaded for some reason + */ + private void loadUserlist(final Properties userList) + throws BuildException { + if (null != usersFile) { + try { + userList.load(new FileInputStream(usersFile)); + } catch (final IOException ioe) { + throw new BuildException(ioe.toString(), ioe); + } + } + } + + /** + * Filter the specified entries according to an appropriate rule. + * + * @param entrySet the entry set to filter + * @return the filtered entry set + */ + private SvnEntry[] filterEntrySet(final SvnEntry[] entrySet) { + final Vector results = new Vector(); + + for (int i = 0; i < entrySet.length; i++) { + final SvnEntry svnEntry = entrySet[i]; + + if (null != endRevision && !isBeforeEndRevision(svnEntry)) { + //Skip revisions that are too late + continue; + } + results.addElement(svnEntry); + } + + final SvnEntry[] resultArray = new SvnEntry[results.size()]; + + results.copyInto(resultArray); + return resultArray; + } + + /** + * replace all known author's id's with their maven specified names + */ + private void replaceAuthorIdWithName(final Properties userList, + final SvnEntry[] entrySet) { + for (int i = 0; i < entrySet.length; i++) { + + final SvnEntry entry = entrySet[ i ]; + if (userList.containsKey(entry.getAuthor())) { + entry.setAuthor(userList.getProperty(entry.getAuthor())); + } + } + } + + /** + * Print changelog to file specified in task. + * + * @param entrySet the entry set to write. + * @throws BuildException if there is an error writing changelog. + */ + private void writeChangeLog(final SvnEntry[] entrySet) + throws BuildException { + FileOutputStream output = null; + + try { + output = new FileOutputStream(destFile); + + final PrintWriter writer = + new PrintWriter(new OutputStreamWriter(output, "UTF-8")); + + final SvnChangeLogWriter serializer = new SvnChangeLogWriter(); + + serializer.printChangeLog(writer, entrySet); + } catch (final UnsupportedEncodingException uee) { + getProject().log(uee.toString(), Project.MSG_ERR); + } catch (final IOException ioe) { + throw new BuildException(ioe.toString(), ioe); + } finally { + FileUtils.close(output); + } + } + + private static final String PATTERN = "yyyy-MM-dd"; + private static final SimpleDateFormat INPUT_DATE + = new SimpleDateFormat(PATTERN); + + /** + * Checks whether a given entry is before the given end revision, + * using revision numbers or date information as appropriate. + */ + private boolean isBeforeEndRevision(SvnEntry entry) { + if (endRevision.startsWith("{") + && endRevision.length() >= 2 + PATTERN.length() ) { + try { + Date endDate = + INPUT_DATE.parse(endRevision.substring(1, + PATTERN.length() + + 1)); + return entry.getDate().before(endDate); + } catch (ParseException e) { + } + } else { + try { + int endRev = Integer.parseInt(endRevision); + int entryRev = Integer.parseInt(entry.getRevision()); + return endRev >= entryRev; + } catch (NumberFormatException e) { + } // end of try-catch + } + // failed to parse revision, use a save fallback + return true; + } +} + diff --git a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogWriter.java b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogWriter.java new file mode 100644 index 000000000..f220b27f6 --- /dev/null +++ b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogWriter.java @@ -0,0 +1,81 @@ +/* + * 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.PrintWriter; +import java.text.SimpleDateFormat; + +/** + * Class used to generate an XML changelog. + */ +public class SvnChangeLogWriter { + /** output format for dates written to xml file */ + private static final SimpleDateFormat OUTPUT_DATE + = new SimpleDateFormat("yyyy-MM-dd"); + /** output format for times written to xml file */ + private static final SimpleDateFormat OUTPUT_TIME + = new SimpleDateFormat("HH:mm"); + + /** + * Print out the specified entries. + * + * @param output writer to which to send output. + * @param entries the entries to be written. + */ + public void printChangeLog(final PrintWriter output, + final SvnEntry[] entries) { + output.println(""); + output.println(""); + for (int i = 0; i < entries.length; i++) { + final SvnEntry entry = entries[i]; + + printEntry(output, entry); + } + output.println(""); + output.flush(); + output.close(); + } + + + /** + * Print out an individual entry in changelog. + * + * @param entry the entry to print + * @param output writer to which to send output. + */ + private void printEntry(final PrintWriter output, final SvnEntry entry) { + output.println("\t"); + output.println("\t\t" + OUTPUT_DATE.format(entry.getDate()) + + ""); + output.println("\t\t"); + output.println("\t\t"); + output.println("\t\t"); + + String[] paths = entry.getPaths(); + for (int i = 0; i < paths.length; i++) { + output.println("\t\t"); + output.println("\t\t\t"); + output.println("\t\t"); + } + output.println("\t\t"); + output.println("\t"); + } +} + diff --git a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java new file mode 100644 index 000000000..9babcc058 --- /dev/null +++ b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java @@ -0,0 +1,115 @@ +/* + * 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.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; + +public class SvnEntry { + private final Date date; + private final String revision; + private String author; + private final String message; + private final ArrayList paths = new ArrayList(); + + /** + * Creates a new instance of a SvnEntry + * @param date the date + * @param author the author + * @param message a message to be added to the revision + */ + public SvnEntry(final Date date, final String revision, + final String author, final String message) { + this(date, revision, author, message, Collections.EMPTY_LIST); + } + + /** + * Creates a new instance of a SvnEntry + * @param date the date + * @param author the author + * @param message a message to be added to the revision + */ + public SvnEntry(final Date date, final String revision, + final String author, final String message, + final Collection paths) { + this.date = date; + this.revision = revision; + this.author = author; + this.message = message; + this.paths.addAll(paths); + } + + /** + * Adds a path to the SvnEntry + * @param path the path to add + * @param revision the revision + */ + public void addPath(final String name) { + paths.add(name); + } + + /** + * Gets the date of the SvnEntry + * @return the date + */ + public Date getDate() { + return date; + } + + /** + * Gets the revision of the SvnEntry + * @return the date + */ + public String getRevision() { + return revision; + } + + /** + * Sets the author of the SvnEntry + * @param author the author + */ + public void setAuthor(final String author) { + this.author = author; + } + + /** + * Gets the author of the SvnEntry + * @return the author + */ + public String getAuthor() { + return author; + } + + /** + * Gets the message for the SvnEntry + * @return the message + */ + public String getMessage() { + return message; + } + + /** + * Gets the paths in this SvnEntry + * @return the files + */ + public String[] getPaths() { + return (String[]) paths.toArray(new String[paths.size()]); + } + +} diff --git a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml index 880d81fae..400e8f726 100644 --- a/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml +++ b/proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml @@ -19,4 +19,8 @@ name="svn" classname="org.apache.tools.ant.taskdefs.svn.Svn" /> +