Integrate cvslib to provide java based access to CVS. Requires jar file attached
to JIRA issue MAVEN-968. http://jira.codehaus.org/secure/ViewIssue.jspa?key=MAVEN-968 git-svn-id: https://svn.apache.org/repos/asf/maven/maven-1/plugins/trunk@114231 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
1 parent
a21d7b79c9
commit
9100b172d0
8 files changed
+841
-118
No files matched your search
@@ -6,3 +6,4 @@ maven.xdoc.version=${pom.currentVersion}
|
||||
maven.license.licenseFile=${basedir}/../../../LICENSE.txt
|
||||
maven.checkstyle.header.file=${basedir}/../../../LICENSE.txt
|
||||
maven.checkstyle.format = turbine
|
||||
maven.junit.fork=true
|
||||
+16
-2
@@ -5,7 +5,7 @@
|
||||
<pomVersion>3</pomVersion>
|
||||
<id>maven-changelog-plugin</id>
|
||||
<name>Maven Changelog Plug-in</name>
|
||||
<currentVersion>1.3</currentVersion>
|
||||
<currentVersion>1.4-dev</currentVersion>
|
||||
<description/>
|
||||
<shortDescription>Produce SCM changelog reports</shortDescription>
|
||||
<url>http://maven.apache.org/reference/plugins/changelog/</url>
|
||||
@@ -35,6 +35,15 @@
|
||||
<role>Java Developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Eric Pugh</name>
|
||||
<id>epugh</id>
|
||||
<email>epugh@upstate.com</email>
|
||||
<organization/>
|
||||
<roles>
|
||||
<role>Java Developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Emmanuel Venisse</name>
|
||||
<id>evenisse</id>
|
||||
@@ -55,7 +64,7 @@
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
<dependencies>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<id>ant</id>
|
||||
<version>1.5.3-1</version>
|
||||
@@ -79,6 +88,11 @@
|
||||
<id>junit</id>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>netbeans</groupId>
|
||||
<artifactId>cvslib</artifactId>
|
||||
<version>200310240100</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<id>regexp</id>
|
||||
<version>1.2</version>
|
||||
|
||||
@@ -1,94 +1,87 @@
|
||||
package org.apache.maven.cvslib;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
/*
|
||||
* ==================================================================== The
|
||||
* Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002 The Apache Software Foundation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The end-user documentation included with the redistribution, if any,
|
||||
* must include the following acknowledgment: "This product includes software
|
||||
* developed by the Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself, if and
|
||||
* wherever such third-party acknowledgments normally appear.
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and "Apache Maven"
|
||||
* must not be used to endorse or promote products derived from this software
|
||||
* without prior written permission. For written permission, please contact
|
||||
* apache@apache.org.
|
||||
* 5. Products derived from this software may not be called "Apache", "Apache
|
||||
* Maven", nor may "Apache" appear in their name, without prior written
|
||||
* permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* on behalf of the Apache Software Foundation. For more information on the
|
||||
* Apache Software Foundation, please see <http://www.apache.org/> .
|
||||
*
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringBufferInputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
// commons imports
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
// maven imports
|
||||
import org.apache.maven.changelog.AbstractChangeLogGenerator;
|
||||
import org.apache.maven.changelog.ChangeLogParser;
|
||||
import org.apache.maven.project.Repository;
|
||||
import org.apache.maven.util.AsyncStreamReader;
|
||||
// ant imports
|
||||
import org.apache.tools.ant.types.Commandline;
|
||||
|
||||
/**
|
||||
* A CVS implementation of the {@link org.apache.maven.changelog.ChangeLog}
|
||||
* interface.
|
||||
*
|
||||
* @task Check CVS exists first by running cvs -version instead of current hack
|
||||
*
|
||||
*
|
||||
* @author Glenn McAllister
|
||||
* @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
|
||||
* @author <a href="mailto:jeff.martin@synamic.co.uk">Jeff Martin</a>
|
||||
* @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
|
||||
* @author <a href="mailto:dion@multitask.com.au">dIon Gillard</a>
|
||||
* @author <a href="mailto:bodewig@apache.org">Stefan Bodewig</a>
|
||||
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
|
||||
* @author <a href="mailto:pete-apache-dev@kazmier.com">Pete Kazmier</a>
|
||||
* @version
|
||||
* $Id: CvsChangeLogGenerator.java,v 1.6 2003/04/11 18:53:19 bwalding Exp $
|
||||
* @version $Id: CvsChangeLogGenerator.java,v 1.6 2003/04/11 18:53:19 bwalding
|
||||
* Exp $
|
||||
*/
|
||||
class CvsChangeLogGenerator extends AbstractChangeLogGenerator
|
||||
{
|
||||
/** Log */
|
||||
private static final Log LOG = LogFactory.getLog(CvsChangeLogGenerator.class);
|
||||
private static final Log LOG =
|
||||
LogFactory.getLog(CvsChangeLogGenerator.class);
|
||||
|
||||
public static final int POS_SCM = 0;
|
||||
public static final int POS_SCM_TYPE = 1;
|
||||
@@ -97,19 +90,59 @@ class CvsChangeLogGenerator extends AbstractChangeLogGenerator
|
||||
public static final int POS_SCM_PATH = 4;
|
||||
public static final int POS_SCM_MODULE = 5;
|
||||
|
||||
|
||||
/**
|
||||
* @return the cvs command line to be executed.
|
||||
*/
|
||||
* Execute cvslib client driving the given parser.
|
||||
*
|
||||
* @param parser A {@link ChangeLogParser parser}to process the scm
|
||||
* output.
|
||||
* @return A collection of {@link ChangeLogEntry entries}parsed from the
|
||||
* scm output.
|
||||
* @throws IOException When there are issues executing scm.
|
||||
* @see ChangeLogGenerator#getEntries(ChangeLogParser)
|
||||
*/
|
||||
public Collection getEntries(ChangeLogParser parser) throws IOException
|
||||
{
|
||||
if (parser == null)
|
||||
{
|
||||
throw new NullPointerException("parser cannot be null");
|
||||
}
|
||||
|
||||
if (base == null)
|
||||
{
|
||||
throw new NullPointerException("basedir must be set");
|
||||
}
|
||||
|
||||
if (!base.exists())
|
||||
{
|
||||
throw new FileNotFoundException(
|
||||
"Cannot find base dir " + base.getAbsolutePath());
|
||||
}
|
||||
|
||||
clParser = parser;
|
||||
CvsConnection connection = new CvsConnection();
|
||||
String[] args = getScmLogCommand().getArguments();
|
||||
CvsLogListener ml = new CvsLogListener();
|
||||
|
||||
CvsConnection.processCommand(args, this.changeLogExecutor.getBasedir().toString(), ml);
|
||||
|
||||
entries = clParser.parse(new StringBufferInputStream(ml.getStdout().toString()));
|
||||
|
||||
return entries;
|
||||
}
|
||||
/**
|
||||
* @return the cvs command line to be executed.
|
||||
*/
|
||||
protected Commandline getScmLogCommand()
|
||||
{
|
||||
String tokens[] = Repository.splitSCMConnection(getConnection());
|
||||
|
||||
|
||||
if (!tokens[POS_SCM_TYPE].equals("cvs"))
|
||||
{
|
||||
throw new IllegalArgumentException("repository connection string" + " does not specify 'cvs' as the scm");
|
||||
throw new IllegalArgumentException(
|
||||
"repository connection string"
|
||||
+ " does not specify 'cvs' as the scm");
|
||||
}
|
||||
|
||||
|
||||
Commandline command = new Commandline();
|
||||
|
||||
command.setExecutable("cvs");
|
||||
@@ -120,26 +153,30 @@ class CvsChangeLogGenerator extends AbstractChangeLogGenerator
|
||||
// :pserver:anoncvs@cvs.apache.org:/home/cvspublic
|
||||
// use tokens 3+4+5
|
||||
String connectionBuffer = "";
|
||||
|
||||
|
||||
if (tokens[POS_SCM_SUBTYPE].equalsIgnoreCase("local"))
|
||||
{
|
||||
// use the local repository directory eg. '/home/cvspublic'
|
||||
connectionBuffer = tokens[POS_SCM_PATH];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tokens[POS_SCM_SUBTYPE].equalsIgnoreCase("lserver"))
|
||||
else
|
||||
{
|
||||
if (tokens[POS_SCM_SUBTYPE].equalsIgnoreCase("lserver"))
|
||||
{
|
||||
//create the cvsroot as the local socket cvsroot
|
||||
connectionBuffer = tokens[POS_SCM_USERHOST] + ":" + tokens[POS_SCM_PATH];
|
||||
connectionBuffer =
|
||||
tokens[POS_SCM_USERHOST] + ":" + tokens[POS_SCM_PATH];
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
//create the cvsroot as the remote cvsroot
|
||||
connectionBuffer =
|
||||
":" + tokens[POS_SCM_SUBTYPE]
|
||||
+ ":" + tokens[POS_SCM_USERHOST]
|
||||
+ ":" + tokens[POS_SCM_PATH];
|
||||
":"
|
||||
+ tokens[POS_SCM_SUBTYPE]
|
||||
+ ":"
|
||||
+ tokens[POS_SCM_USERHOST]
|
||||
+ ":"
|
||||
+ tokens[POS_SCM_PATH];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,36 +191,37 @@ class CvsChangeLogGenerator extends AbstractChangeLogGenerator
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the CVS command-line argument that is used to specify
|
||||
* the appropriate date range.
|
||||
*
|
||||
* @param before The starting point.
|
||||
* @param to The ending point.
|
||||
* @return A string that can be used to specify a date to a scm
|
||||
* system.
|
||||
*/
|
||||
/**
|
||||
* Construct the CVS command-line argument that is used to specify the
|
||||
* appropriate date range.
|
||||
*
|
||||
* @param before The starting point.
|
||||
* @param to The ending point.
|
||||
* @return A string that can be used to specify a date to a scm system.
|
||||
*/
|
||||
protected String getScmDateArgument(Date before, Date to)
|
||||
{
|
||||
SimpleDateFormat outputDate = new SimpleDateFormat("yyyy-MM-dd");
|
||||
return "-d " + outputDate.format(before) + "<" + outputDate.format(to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ChangeLogParser IOExceptions.
|
||||
*
|
||||
* @param ioe The IOException thrown.
|
||||
* @throws IOException If the handler doesn't wish to handle the
|
||||
* exception.
|
||||
*/
|
||||
/**
|
||||
* Handle ChangeLogParser IOExceptions.
|
||||
*
|
||||
* @param ioe The IOException thrown.
|
||||
* @throws IOException If the handler doesn't wish to handle the exception.
|
||||
*/
|
||||
protected void handleParserException(IOException ioe) throws IOException
|
||||
{
|
||||
if (ioe.getMessage().indexOf("CreateProcess") != -1 || ioe.getMessage().indexOf("cvs: not found") != -1)
|
||||
if (ioe.getMessage().indexOf("CreateProcess") != -1
|
||||
|| ioe.getMessage().indexOf("cvs: not found") != -1)
|
||||
{
|
||||
// can't find CVS on Win32 or Linux...
|
||||
if (LOG.isWarnEnabled())
|
||||
{
|
||||
LOG.warn("Unable to find cvs executable. " + "Changelog will be empty");
|
||||
LOG.warn(
|
||||
"Unable to find cvs executable. "
|
||||
+ "Changelog will be empty");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -193,39 +231,40 @@ class CvsChangeLogGenerator extends AbstractChangeLogGenerator
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the error stream for reading from cvs log. This stream will be read
|
||||
* on a separate thread.
|
||||
* @param is - an {@link java.io.InputStream}
|
||||
*/
|
||||
* Set the error stream for reading from cvs log. This stream will be read
|
||||
* on a separate thread.
|
||||
*
|
||||
* @param is - an {@link java.io.InputStream}
|
||||
*/
|
||||
public void setProcessErrorStream(InputStream is)
|
||||
{
|
||||
errorReader = new CvsAsyncErrorReader(is);
|
||||
}
|
||||
|
||||
/**
|
||||
* A private AsyncStreamReader class that "swallows" the "cvs server:
|
||||
* Logging" lines.
|
||||
*/
|
||||
* A private AsyncStreamReader class that "swallows" the "cvs server:
|
||||
* Logging" lines.
|
||||
*/
|
||||
private static class CvsAsyncErrorReader extends AsyncStreamReader
|
||||
{
|
||||
/**
|
||||
* The obvious constructor.
|
||||
*
|
||||
* @param anInputStream the input stream to consume
|
||||
*/
|
||||
* The obvious constructor.
|
||||
*
|
||||
* @param anInputStream the input stream to consume
|
||||
*/
|
||||
public CvsAsyncErrorReader(InputStream anInputStream)
|
||||
{
|
||||
super(anInputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the line does not start with "cvs server: Logging", it's ok to
|
||||
* consume it.
|
||||
*
|
||||
* @param line the line to check
|
||||
* @return <code>true</code> if the line does not start with "cvs
|
||||
* server: Logging"
|
||||
*/
|
||||
* If the line does not start with "cvs server: Logging", it's ok to
|
||||
* consume it.
|
||||
*
|
||||
* @param line the line to check
|
||||
* @return <code>true</code> if the line does not start with "cvs
|
||||
* server: Logging"
|
||||
*/
|
||||
protected boolean okToConsume(String line)
|
||||
{
|
||||
return !line.startsWith("cvs server: Logging");
|
||||
|
||||
@@ -0,0 +1,442 @@
|
||||
package org.apache.maven.cvslib;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.netbeans.lib.cvsclient.CVSRoot;
|
||||
import org.netbeans.lib.cvsclient.Client;
|
||||
import org.netbeans.lib.cvsclient.admin.StandardAdminHandler;
|
||||
import org.netbeans.lib.cvsclient.command.Command;
|
||||
import org.netbeans.lib.cvsclient.command.CommandException;
|
||||
import org.netbeans.lib.cvsclient.command.GlobalOptions;
|
||||
import org.netbeans.lib.cvsclient.commandLine.CommandFactory;
|
||||
import org.netbeans.lib.cvsclient.commandLine.GetOpt;
|
||||
import org.netbeans.lib.cvsclient.connection.AuthenticationException;
|
||||
import org.netbeans.lib.cvsclient.connection.Connection;
|
||||
import org.netbeans.lib.cvsclient.connection.ConnectionFactory;
|
||||
import org.netbeans.lib.cvsclient.connection.PServerConnection;
|
||||
import org.netbeans.lib.cvsclient.connection.StandardScrambler;
|
||||
import org.netbeans.lib.cvsclient.event.CVSListener;
|
||||
|
||||
/**
|
||||
* A Cvs connection that simulates a command line interface.
|
||||
*
|
||||
* @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
|
||||
*/
|
||||
public class CvsConnection
|
||||
{
|
||||
|
||||
/** Log */
|
||||
private static final Log LOG =
|
||||
LogFactory.getLog(CvsConnection.class);
|
||||
/**
|
||||
* The path to the repository on the server
|
||||
*/
|
||||
private String repository;
|
||||
|
||||
/**
|
||||
* The local path to use to perform operations (the top level)
|
||||
*/
|
||||
private String localPath;
|
||||
|
||||
/**
|
||||
* The connection to the server
|
||||
*/
|
||||
private Connection connection;
|
||||
|
||||
/**
|
||||
* The client that manages interactions with the server
|
||||
*/
|
||||
private Client client;
|
||||
|
||||
/**
|
||||
* The global options being used. GlobalOptions are only global for a
|
||||
* particular command.
|
||||
*/
|
||||
private GlobalOptions globalOptions;
|
||||
|
||||
/**
|
||||
* Execute a configured CVS command
|
||||
*
|
||||
* @param command the command to execute
|
||||
* @throws CommandException if there is an error running the command
|
||||
*/
|
||||
public void executeCommand(Command command)
|
||||
throws CommandException, AuthenticationException
|
||||
{
|
||||
client.executeCommand(command, globalOptions);
|
||||
}
|
||||
|
||||
public void setRepository(String repository)
|
||||
{
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public void setLocalPath(String localPath)
|
||||
{
|
||||
this.localPath = localPath;
|
||||
}
|
||||
|
||||
public void setGlobalOptions(GlobalOptions globalOptions)
|
||||
{
|
||||
this.globalOptions = globalOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the connection and the client and connects.
|
||||
*/
|
||||
private void connect(CVSRoot root, String password)
|
||||
throws IllegalArgumentException, AuthenticationException
|
||||
{
|
||||
connection = ConnectionFactory.getConnection(root);
|
||||
if (CVSRoot.METHOD_PSERVER.equals(root.getMethod()))
|
||||
{
|
||||
((PServerConnection) connection).setEncodedPassword(password);
|
||||
}
|
||||
connection.open();
|
||||
|
||||
client = new Client(connection, new StandardAdminHandler());
|
||||
client.setLocalPath(localPath);
|
||||
}
|
||||
|
||||
private void addListener(CVSListener listener)
|
||||
{
|
||||
if (client != null)
|
||||
{
|
||||
// add a listener to the client
|
||||
client.getEventManager().addCVSListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtain the CVS root, either from the -D option cvs.root or from the CVS
|
||||
* directory
|
||||
*
|
||||
* @return the CVSRoot string
|
||||
*/
|
||||
private static String getCVSRoot(String workingDir)
|
||||
{
|
||||
String root = null;
|
||||
BufferedReader r = null;
|
||||
if (workingDir == null)
|
||||
{
|
||||
workingDir = System.getProperty("user.dir");
|
||||
}
|
||||
try
|
||||
{
|
||||
File f = new File(workingDir);
|
||||
File rootFile = new File(f, "CVS/Root");
|
||||
if (rootFile.exists())
|
||||
{
|
||||
r = new BufferedReader(new FileReader(rootFile));
|
||||
root = r.readLine();
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (r != null)
|
||||
r.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println("Warning: could not close CVS/Root file!");
|
||||
}
|
||||
}
|
||||
if (root == null)
|
||||
{
|
||||
root = System.getProperty("cvs.root");
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process global options passed into the application
|
||||
*
|
||||
* @param args the argument list, complete
|
||||
* @param globalOptions the global options structure that will be passed to
|
||||
* the command
|
||||
*/
|
||||
private static int processGlobalOptions(
|
||||
String[] args,
|
||||
GlobalOptions globalOptions)
|
||||
{
|
||||
final String getOptString = globalOptions.getOptString();
|
||||
GetOpt go = new GetOpt(args, getOptString);
|
||||
int ch = -1;
|
||||
boolean usagePrint = false;
|
||||
while ((ch = go.getopt()) != GetOpt.optEOF)
|
||||
{
|
||||
//System.out.println("Global option '"+((char) ch)+"',
|
||||
// '"+go.optArgGet()+"'");
|
||||
boolean success =
|
||||
globalOptions.setCVSCommand((char) ch, go.optArgGet());
|
||||
if (!success)
|
||||
usagePrint = true;
|
||||
}
|
||||
|
||||
return go.optIndexGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the password in the .cvspass file. This file is looked for in the
|
||||
* user.home directory if the option cvs.passfile is not set
|
||||
*
|
||||
* @param CVSRoot the CVS root for which the password is being searched
|
||||
* @return the password, scrambled
|
||||
*/
|
||||
private static String lookupPassword(String CVSRoot)
|
||||
{
|
||||
File passFile =
|
||||
new File(
|
||||
System.getProperty(
|
||||
"cvs.passfile",
|
||||
System.getProperty("user.home") + "/.cvspass"));
|
||||
|
||||
BufferedReader reader = null;
|
||||
String password = null;
|
||||
|
||||
try
|
||||
{
|
||||
reader = new BufferedReader(new FileReader(passFile));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null)
|
||||
{
|
||||
if (line.startsWith(CVSRoot))
|
||||
{
|
||||
password = line.substring(CVSRoot.length() + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.error("Could not read password for host: " + e);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (reader != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
reader.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.error("Warning: could not close password file.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (password == null)
|
||||
{
|
||||
LOG.error(
|
||||
"Didn't find password for CVSROOT '" + CVSRoot + "'.");
|
||||
}
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the CVS command passed in args[] array with all necessary
|
||||
* options. The only difference from main() method is, that this method
|
||||
* does not exit the JVM and provides command output.
|
||||
*
|
||||
* @param args The command with options
|
||||
* @param files The files to execute the command on.
|
||||
* @param stdout The standard output of the command
|
||||
*/
|
||||
public static boolean processCommand(
|
||||
String[] args,
|
||||
String localPath,
|
||||
CVSListener listener)
|
||||
{
|
||||
|
||||
// Set up the CVSRoot. Note that it might still be null after this
|
||||
// call if the user has decided to set it with the -d command line
|
||||
// global option
|
||||
GlobalOptions globalOptions = new GlobalOptions();
|
||||
globalOptions.setCVSRoot(getCVSRoot(localPath));
|
||||
|
||||
// Set up any global options specified. These occur before the
|
||||
// name of the command to run
|
||||
int commandIndex = -1;
|
||||
try
|
||||
{
|
||||
commandIndex = processGlobalOptions(args, globalOptions);
|
||||
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
LOG.error("Invalid argument: " + e);
|
||||
return false;
|
||||
}
|
||||
|
||||
// if we don't have a CVS root by now, the user has messed up
|
||||
if (globalOptions.getCVSRoot() == null)
|
||||
{
|
||||
LOG.error(
|
||||
"No CVS root is set. Use the cvs.root "
|
||||
+ "property, e.g. java -Dcvs.root=\":pserver:user@host:/usr/cvs\""
|
||||
+ " or start the application in a directory containing a CVS subdirectory"
|
||||
+ " or use the -d command switch.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse the CVS root into its constituent parts
|
||||
CVSRoot root = null;
|
||||
final String cvsRoot = globalOptions.getCVSRoot();
|
||||
try
|
||||
{
|
||||
root = CVSRoot.parse(cvsRoot);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
LOG.error(
|
||||
"Incorrect format for CVSRoot: "
|
||||
+ cvsRoot
|
||||
+ "\nThe correct format is: "
|
||||
+ "[:method:][[user][:password]@][hostname:[port]]/path/to/repository"
|
||||
+ "\nwhere \"method\" is pserver.");
|
||||
return false;
|
||||
}
|
||||
|
||||
final String command = args[commandIndex];
|
||||
|
||||
// this is not login, but a 'real' cvs command, so construct it,
|
||||
// set the options, and then connect to the server and execute it
|
||||
|
||||
Command c = null;
|
||||
try
|
||||
{
|
||||
c =
|
||||
CommandFactory.getDefault().createCommand(
|
||||
command,
|
||||
args,
|
||||
++commandIndex,
|
||||
globalOptions,
|
||||
localPath);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
LOG.error("Illegal argument: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
String password = null;
|
||||
|
||||
if (CVSRoot.METHOD_PSERVER.equals(root.getMethod()))
|
||||
{
|
||||
password = root.getPassword();
|
||||
if (password != null)
|
||||
{
|
||||
password = StandardScrambler.getInstance().scramble(password);
|
||||
}
|
||||
else
|
||||
{
|
||||
password = lookupPassword(cvsRoot);
|
||||
if (password == null)
|
||||
{
|
||||
password = StandardScrambler.getInstance().scramble("");
|
||||
// an empty password
|
||||
}
|
||||
}
|
||||
}
|
||||
CvsConnection cvsCommand = new CvsConnection();
|
||||
cvsCommand.setGlobalOptions(globalOptions);
|
||||
cvsCommand.setRepository(root.getRepository());
|
||||
// the local path is just the path where we executed the
|
||||
// command. This is the case for command-line CVS but not
|
||||
// usually for GUI front-ends
|
||||
cvsCommand.setLocalPath(localPath);
|
||||
try
|
||||
{
|
||||
cvsCommand.connect(root, password);
|
||||
|
||||
|
||||
cvsCommand.addListener(listener);
|
||||
cvsCommand.executeCommand(c);
|
||||
|
||||
}
|
||||
catch (Exception t)
|
||||
{
|
||||
LOG.error("Error: " + t,t);
|
||||
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package org.apache.maven.cvslib;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import org.netbeans.lib.cvsclient.event.CVSAdapter;
|
||||
import org.netbeans.lib.cvsclient.event.MessageEvent;
|
||||
|
||||
/**
|
||||
* A basic implementation of a CVS listener. It merely saves up
|
||||
* into StringBuffers the stdout and stderr printstreams.
|
||||
*
|
||||
* @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
|
||||
*/
|
||||
public class CvsLogListener extends CVSAdapter
|
||||
{
|
||||
private final StringBuffer taggedLine = new StringBuffer();
|
||||
private StringBuffer stdout = new StringBuffer();
|
||||
private StringBuffer stderr = new StringBuffer();
|
||||
|
||||
/**
|
||||
* Called when the server wants to send a message to be displayed to the
|
||||
* user. The message is only for information purposes and clients can
|
||||
* choose to ignore these messages if they wish.
|
||||
*
|
||||
* @param e the event
|
||||
*/
|
||||
public void messageSent(MessageEvent e)
|
||||
{
|
||||
String line = e.getMessage();
|
||||
StringBuffer stream = e.isError() ? stderr : stdout;
|
||||
|
||||
if (e.isTagged())
|
||||
{
|
||||
String message =
|
||||
MessageEvent.parseTaggedMessage(taggedLine, e.getMessage());
|
||||
if (message != null)
|
||||
{
|
||||
//stream.println(message);
|
||||
stream.append(message+"\n");
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//stream.println(line);
|
||||
stream.append(line+"\n");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the standard output from cvs as a StringBuffer..
|
||||
*/
|
||||
public StringBuffer getStdout()
|
||||
{
|
||||
return stdout;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,8 +56,6 @@ package org.apache.maven.cvslib;
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.project.Repository;
|
||||
import org.apache.maven.util.EnhancedStringTokenizer;
|
||||
@@ -67,7 +65,7 @@ import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author <a href="bwalding@jakarta.org">Ben Walding</a>
|
||||
* @version $Id: CvsChangeLogGeneratorTest.java,v 1.5 2003/04/11 18:53:19 bwalding Exp $
|
||||
* @version $Id: CvsChangeLogGeneratorTest.java,v 1.6 2003/10/25 18:33:13 epugh Exp $
|
||||
*/
|
||||
class ExposeGenerator extends CvsChangeLogGenerator
|
||||
{
|
||||
@@ -80,7 +78,7 @@ class ExposeGenerator extends CvsChangeLogGenerator
|
||||
|
||||
/**
|
||||
* @author <a href="bwalding@jakarta.org">Ben Walding</a>
|
||||
* @version $Id: CvsChangeLogGeneratorTest.java,v 1.5 2003/04/11 18:53:19 bwalding Exp $
|
||||
* @version $Id: CvsChangeLogGeneratorTest.java,v 1.6 2003/10/25 18:33:13 epugh Exp $
|
||||
*/
|
||||
public class CvsChangeLogGeneratorTest extends TestCase
|
||||
{
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
package org.apache.maven.cvslib;
|
||||
|
||||
/* ====================================================================
|
||||
* The Apache Software License, Version 1.1
|
||||
*
|
||||
* Copyright (c) 2002 The Apache Software Foundation. All rights
|
||||
* reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The end-user documentation included with the redistribution,
|
||||
* if any, must include the following acknowledgment:
|
||||
* "This product includes software developed by the
|
||||
* Apache Software Foundation (http://www.apache.org/)."
|
||||
* Alternately, this acknowledgment may appear in the software itself,
|
||||
* if and wherever such third-party acknowledgments normally appear.
|
||||
*
|
||||
* 4. The names "Apache" and "Apache Software Foundation" and
|
||||
* "Apache Maven" must not be used to endorse or promote products
|
||||
* derived from this software without prior written permission. For
|
||||
* written permission, please contact apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache",
|
||||
* "Apache Maven", nor may "Apache" appear in their name, without
|
||||
* prior written permission of the Apache Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*/
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.netbeans.lib.cvsclient.event.MessageEvent;
|
||||
|
||||
|
||||
/**
|
||||
* Test cases for {@link CvsLogListener}
|
||||
* @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
|
||||
* @version $Id: CvsLogListenerTest.java,v 1.1 2003/10/25 18:33:13 epugh Exp $
|
||||
*/
|
||||
public class CvsLogListenerTest extends TestCase
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Create a test with the given name
|
||||
* @param testName the name of the test
|
||||
*/
|
||||
public CvsLogListenerTest(String testName)
|
||||
{
|
||||
super(testName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of listening to a regular output
|
||||
* @throws Exception when there is an unexpected problem
|
||||
*/
|
||||
public void testNormalEvent() throws Exception
|
||||
{
|
||||
String MESSAGE = "I am a message";
|
||||
CvsLogListener listener = new CvsLogListener();
|
||||
MessageEvent me = new MessageEvent("souce",MESSAGE,false);
|
||||
listener.messageSent(me);
|
||||
assertTrue(listener.getStdout().indexOf(MESSAGE)>-1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of listening to an error
|
||||
* @throws Exception when there is an unexpected problem
|
||||
*/
|
||||
public void testErrorEvent() throws Exception
|
||||
{
|
||||
String MESSAGE = "I am a message";
|
||||
CvsLogListener listener = new CvsLogListener();
|
||||
MessageEvent me = new MessageEvent("souce",MESSAGE,true);
|
||||
listener.messageSent(me);
|
||||
assertTrue(listener.getStdout().indexOf(MESSAGE)==-1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -7,6 +7,12 @@
|
||||
</properties>
|
||||
|
||||
<body>
|
||||
<release version="1.4-dev" date="in cvs">
|
||||
<action dev="epugh" type="update">
|
||||
Added java based CVS library using cvslib. Removed
|
||||
requirement for cvs executable.
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.3" date="2003-09-29">
|
||||
<action dev="dion" type="update">
|
||||
MAVEN-811. Add support of IBM Rational ClearCase SCM.
|
||||
|
||||
Reference in new issue
Block a user