Hi,
a while ago I posted some functionality for synchronising a maven project with a
cvs repository. I've migrated this funcionality so it can be used directly
within maven.
brief summary of what CvsSynch does:
1) gets your file system in synch with modifications in cvs
2) performs a full clean build and runs all tests
3) if all tests pass, modifies cvs to bring in synch with modifications on your
file system
*********************************************
2 new classes
org.apache.maven.cvsutil.CvsSynch
org.apache.maven.util.ToStringUtil
add them to jakarta-turbine-maven/src/java/org.........
build the classes
jakarta-turbine-maven>ant maven:install-jar
***************************************************
add this target to {maven.home}/build-maven.xml
<target name="cvs-synch" depends="local-init,env">
<taskdef name="cvssynch" classname="org.apache.maven.cvsutil.CvsSynch">
<classpath refid="maven-classpath"/>
</taskdef>
<cvssynch projectDescriptor="project.xml">
<!-- some nested ant call to perform build / tests etc -->
</cvssynch>
</target>
***************************************************
add this target to your project build.xml
<target name="maven:cvs-synch">
<ant antfile="${maven.home}/build-maven.xml" target="cvs-synch"/>
</target>
*******************************************************************
to execute
my.project.home>ant maven:cvs-synch
BEWARE. If you are using a username / password in project.xml that has write
access to your cvs repository, this will modify the cvs repository.
*****************************************************************
package org.apache.maven.cvsutil;
import org.apache.tools.ant.taskdefs.Cvs;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.BuildException;
import org.apache.maven.project.Project;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.Environment;
import org.apache.tools.ant.taskdefs.Ant;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.maven.util.ToStringUtil;
import java.util.Collection;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.maven.executor.ProjectExecutor;
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
/**
*
* Task to manage synchronisation of filesystem with cvs. The Filesystem
* is brought up to date with changes in cvs This is done by performing a
* update -n . the output file of this command is parsed to identify what has
* to be done. If the file contains a 'C' the build is failed as cvs is unable
* to reconcile the differences between the filesystem and cvs. Files requiring
* updating from CVS are identified by 'M'. Files in cvs but absent ('U') from the file
* system could either added to cvs or removed from the filesystem. The difference
* is identified by parsing the appropriate CVS/Entries file. Files added to cvs
* are brought to the fs. The fs is now in synch with cvs. the project is built
* and tested via the nested ant task. If the build and all tests suceed.
* New files are added to CVS, removed files are removed and all chages are
* committed.
* @author [EMAIL PROTECTED]
* todo back up current fs prior to making modifications in order to rollback.
* this functionality could be used just for reporting purposes to remind developer
* of cvs tasks to perform.
*/
public class CvsSynch extends ProjectExecutor
// implements ExecuteStreamHandler
{
private Cvs mCvs = null;
private Ant mAntTask = null;
/**
* the package/module to check out.
*/
// private String mPackage = null;
// private File mComponentsDirectory;
// private File mComponentDirectory;
private File mUpdateLog = null;
private Collection mFilesToAdd = null;
private Collection mFilesToRemove = null;
private Collection mFilesToMerge = null;
private Collection mFilesToGet = null;
private Collection mFilesWithConflicts = null;
private HashMap mEntriesMap = null;
public CvsSynch(){
mCvs = new Cvs();
mCvs.setFailOnError(true);
mEntriesMap = new HashMap();
}
public void doExecute() throws BuildException {
Project project = getMavenProject();
mCvs.setCvsRoot(project.getCvsRoot());
mCvs.setPackage(project.getCvsModule());
mCvs.setProject(getProject());
mCvs.setDest(getParentDirectory());
try{
//does nothing at the moment
backupCode();
//performs an update to identify what needs doing to which files
doNoexecUpdate();
//merge changed files
doMerge();
//get missing files
doGet();
//do any nested test - responsible for performing the build
if(mAntTask != null){
System.out.println("performing nested test task");
mAntTask.execute();
}
// if tests pass add missing files to cvs
doAddition();
// remove any files from cvs removed from filesystem
doRemove();
// commit all changes
doCommit();
}
catch(IOException e){
e.printStackTrace();
throw new BuildException(e);
}
}
//todo
private void backupCode(){
}
/**
* writes output of update to /components/mycomponent/cvsupdate/cvsupdate.log
*/
private void doNoexecUpdate(){
System.out.println("generating the synch log file");
mCvs.setNoexec(true);
mCvs.setCommand("update");
File updateLog = getUpdateLog();
mCvs.setOutput(updateLog);
System.out.println("generating the synch log file: " + updateLog);
mCvs.execute();
}
private void parseUpdateLog() throws IOException{
BufferedReader br = new BufferedReader(new FileReader(getUpdateLog()));
ArrayList missingFiles = new ArrayList();
String str = null;
mFilesToAdd = new ArrayList();
mFilesToRemove = new ArrayList();
mFilesToMerge = new ArrayList();
mFilesToGet = new ArrayList();
mFilesWithConflicts = new ArrayList();
while((str = br.readLine()) != null){
if(str.startsWith("? ")){
addToCollection(str,mFilesToAdd);
}
else if(str.startsWith("M ")){
addToCollection(str,mFilesToMerge);
}
else if(str.startsWith("U ")){
if(isRemoved(str)){
addToCollection(str,mFilesToRemove);
}
else{
addToCollection(str,mFilesToGet);
}
}
else if(str.startsWith("C ")){
addToCollection(str,mFilesWithConflicts);
}
}
if(mFilesWithConflicts.size() > 0){
throw new BuildException("The following files have conflicts, please
resolve before proceeding.\n" +
ToStringUtil.toString(mFilesWithConflicts));
}
}
private File getUpdateLog(){
if(mUpdateLog == null){
File buildDir = getBuildDirectory();
mUpdateLog = new File(buildDir, "cvsupdate.log");
}
return mUpdateLog;
}
private File getBuildDirectory() {
String buildDirName = (String)
getProject().getProperties().get("maven.build.dir");
return new File(buildDirName);
}
private File getParentDirectory(){
return new File(getProject().getBaseDir(),"..");
}
/* private File getComponentDirectory(){
if(mComponentDirectory == null){
File componentDirectory = new File(mComponentsDirectory,mPackage);
if(!componentDirectory.exists()){
if(!componentDirectory.mkdir()){
throw new BuildException("unable to create the component
directory: " + componentDirectory.toString());
}
}
mComponentDirectory = componentDirectory;
}
return mComponentDirectory;
}*/
private boolean isRemoved(String str)
throws IOException
{
System.out.println("checking if " + str + " has been removed");
str = str.substring(2);
int idx = str.lastIndexOf("/");
String directory = str.substring(0,idx);
String filename = str.substring(idx) + "/";
System.out.println("dir = " + directory + " filename = " + filename);
String entries = getEntriesFile(directory);
return (entries.indexOf(filename) != -1);
}
private String getEntriesFile(String directory)
throws IOException
{
if('/' != File.separatorChar){
directory = directory.replace('/', File.separatorChar);
}
directory = directory + File.separator + "CVS";
System.out.println("directory = " + directory);
String entries = (String) mEntriesMap.get(directory);
if(entries == null){
File cvsDir = new File(getProject().getBaseDir(), directory);
StringBuffer sb = new StringBuffer();
if(cvsDir.exists()){
System.out.println("directory exists");
File entriesFile = new File(cvsDir,"Entries");
FileReader fr = new FileReader(entriesFile);
BufferedReader br = new BufferedReader(fr);
try{
String str = null;
while((str = br.readLine()) != null){
sb.append(str);
}
}
finally{
closeReader(fr);
closeReader(br);
}
}
entries = sb.toString();
mEntriesMap.put(directory,entries);
}
return entries;
}
private static void addToCollection(String str, Collection col){
str = str.substring(2);
str = str.trim();
col.add(str);
}
/**
* update files on fs that have been modified in cvs
*/
private void doMerge() throws IOException {
System.out.println("files to merge");
Collection col = getFilesToMerge();
ToStringUtil.toStdOut(col);
Iterator it = col.iterator();
mCvs.setNoexec(false);
mCvs.setCommand("update");
mCvs.setOutput(null);
while(it.hasNext()){
String module = (String) it.next();
System.out.println("updating component: " + module);
mCvs.setPackage(module);
mCvs.execute();
}
}
private Collection getFilesToMerge() throws IOException {
if(mFilesToMerge == null){
parseUpdateLog();
}
return mFilesToMerge;
}
/**
* gets missing files onto filesystem from cvs - doesnt get files
* removed from fs, these will be schedulded for removal.
*/
private void doGet() throws IOException {
System.out.println("files to get");
Collection col = getFilesToGet();
ToStringUtil.toStdOut(col);
Iterator it = col.iterator();
mCvs.setNoexec(false);
mCvs.setCommand("checkout");
mCvs.setOutput(null);
while(it.hasNext()){
String module = (String) it.next();
mCvs.setPackage(module);
mCvs.execute();
}
}
private Collection getFilesToGet() throws IOException {
if(mFilesToGet == null){
parseUpdateLog();
}
return mFilesToGet;
}
/**
* adds new files to cvs after successful nested ant task
*/
private void doAddition() throws IOException {
System.out.println("files to add");
Collection col = getFilesToAdd();
ToStringUtil.toStdOut(col);
Iterator it = col.iterator();
mCvs.setNoexec(false);
mCvs.setCommand("add");
mCvs.setOutput(null);
while(it.hasNext()){
String module = (String) it.next();
String filename = module.substring(module.lastIndexOf("/") + 1);
File dir = getDirectoryFromFile(module);
System.out.println("changing dir to " + dir);
mCvs.setDest(dir);
mCvs.setPackage(filename);
mCvs.execute();
}
mCvs.setDest(getParentDirectory());
}
private Collection getFilesToAdd() throws IOException {
if(mFilesToAdd == null){
parseUpdateLog();
}
return mFilesToAdd;
}
/**
* removes files from cvs after successful nested ant task
*/
private void doRemove() throws IOException {
System.out.println("files to remove");
Collection col = getFilesToRemove();
ToStringUtil.toStdOut(col);
Iterator it = col.iterator();
mCvs.setNoexec(false);
mCvs.setCommand("remove");
mCvs.setOutput(null);
while(it.hasNext()){
String module = (String) it.next();
mCvs.setPackage(module);
mCvs.execute();
System.out.println("trying to remove " + module);
}
}
private Collection getFilesToRemove() throws IOException {
if(mFilesToRemove == null){
parseUpdateLog();
}
return mFilesToRemove;
}
/**
* commit all additions, removals and modifications to cvs
*/
private void doCommit() throws IOException {
System.out.println("commiting");
mCvs.setNoexec(false);
mCvs.setCommand("commit -m 'automatic checkin from RepositorySynch task'");
mCvs.setOutput(null);
mCvs.setPackage(getMavenProject().getCvsModule());
File parent = getParentDirectory();
System.out.println("setting component directory to " + parent);
mCvs.setDest(parent);
mCvs.execute();
System.out.println("attempting to commit to central repository");
}
private File getDirectoryFromFile(String file){
String directory = file.substring(0,file.lastIndexOf("/"));
if(File.separatorChar != '/'){
directory = directory.replace('/',File.separatorChar);
}
return new File(getParentDirectory(),directory);
}
// ant task set methods.
/* public void setProject(Project project){
super.setProject(project);
mCvs.setProject(project);
}*/
public void addAnt(Ant antTask){
mAntTask = antTask;
}
/* public void setPort(int port){
System.out.println("setport");
mCvs.setPort(port);
}
public void setPassfile(File passFile){
System.out.println("set passfile");
mCvs.setPassfile(passFile);
}
public void setPackage(String p) {
System.out.println("setPackage");
mPackage = p;
mCvs.setPackage(p);
}
/*
public void setComponentsDirectory(File componentsDirectory){
mComponentsDirectory = componentsDirectory;
mCvs.setDest(mComponentsDirectory);
System.out.println("setting components directory to " + componentsDirectory);
}*/
private static final void closeReader(Reader reader){
if(reader != null){
try{
reader.close();
}
catch(IOException e){
e.printStackTrace();
}
}
}
public void setProcessInputStream(OutputStream is){
}
public void setProcessErrorStream(InputStream is) {}
/**
* Install a handler for the output stream of the subprocess.
*
* @param is input stream to read from the error stream from the subprocess
*/
public void setProcessOutputStream(InputStream is) {}
/**
* Start handling of the streams.
*/
public void start() throws IOException{}
/**
* Stop handling of the streams - will not be restarted.
*/
public void stop(){
}
}
package org.apache.maven.util;
import java.util.Iterator;
import java.util.Collection;
import java.io.PrintStream;
import java.beans.PropertyDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.BeanInfo;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
public class ToStringUtil{
private static HashMap sDescriptorsCache;
static{
sDescriptorsCache = new HashMap();
}
public static final String toString(Iterator it){
StringBuffer sb = new StringBuffer();
while(it.hasNext()){
sb.append(it.next().toString());
sb.append("\n");
}
return sb.toString();
}
public static final String toString(Collection col){
return toString(col.iterator());
}
/* public static final void toStdOut(Iterator it){
}*/
public static final void toStdOut(Collection col){
toPrintStream(col,System.out);
}
/* public static final void toStream(Iterator it, OutputStream os){
}*/
/* public static final void toStream(Collection col, OutputStream os){
}*/
public static final void toPrintStream(Collection col, PrintStream ps){
toPrintStream(col.iterator(),ps);
}
//does not use toString(Iterator) for possible performance reasons if big
//collections are in use.
public static final void toPrintStream(Iterator it, PrintStream ps){
while (it.hasNext()) {
Object obj = it.next();
ps.println(obj.toString());
}
}
public static final String propertiesToString(Object obj){
PropertyDescriptor[] descriptors = getPropertyDescriptors(obj);
final Object[] params = new Object[0];
StringBuffer sb = new StringBuffer();
String name = obj.getClass().getName();
sb.append(name.substring(name.lastIndexOf(".") + 1));
sb.append(":: ");
boolean first = true;
for (int i = 0; i < descriptors.length; i++) {
Method method = descriptors[i].getReadMethod();
if(method != null) {
name = descriptors[i].getName();
if(!name.equals("class")) {
if(!first) {
sb.append(", ");
}
first = false;
sb.append(name);
sb.append("=");
try {
sb.append(method.invoke(obj, params));
}
catch(IllegalAccessException e) {
//sLog.error("exception caught", e);
}
catch(IllegalArgumentException e) {
//sLog.error("exception caught", e);
}
catch(InvocationTargetException e) {
//sLog.error("exception caught", e);
}
}
}
}
return sb.toString();
}
private static PropertyDescriptor[] getPropertyDescriptors(Object bean)
{
if (bean == null)
throw new IllegalArgumentException("No bean specified");
// Look up any cached descriptors for this bean class
String beanClassName = bean.getClass().getName();
PropertyDescriptor descriptors[] = null;
descriptors =
(PropertyDescriptor[]) sDescriptorsCache.get(beanClassName);
if (descriptors != null)
return (descriptors);
// Introspect the bean and cache the generated descriptors
BeanInfo beanInfo = null;
try {
beanInfo = Introspector.getBeanInfo(bean.getClass());
} catch (IntrospectionException e) {
return (new PropertyDescriptor[0]);
}
descriptors = beanInfo.getPropertyDescriptors();
if (descriptors == null)
descriptors = new PropertyDescriptor[0];
sDescriptorsCache.put(beanClassName, descriptors);
return (descriptors);
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>