KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > antmod > scm > impl > CvsSystemImpl


1 package org.antmod.scm.impl;
2
3 import java.io.*;
4 import java.util.ArrayList JavaDoc;
5 import java.util.Collections JavaDoc;
6
7 import org.antmod.conf.AntmodProperties;
8 import org.antmod.scm.ScmDifference;
9 import org.antmod.scm.ScmSystem;
10 import org.antmod.scm.ScmUrl;
11 import org.antmod.scm.ScmVersion;
12 import org.antmod.util.ProcessLauncher;
13 import org.apache.commons.io.FileUtils;
14 import org.apache.commons.io.HexDump;
15 import org.apache.commons.io.IOUtils;
16 import org.apache.commons.lang.StringUtils;
17 import org.apache.commons.lang.SystemUtils;
18 import org.apache.tools.ant.BuildException;
19 import org.apache.tools.ant.taskdefs.FixCRLF;
20
21 /**
22  * CVS repository provider, providing access to CVS
23  * repositories from Antmod.
24  * <p/>
25  * This CVS repository provider is a thin layer on top
26  * of the "cvs" commandline executable, and as such
27  * requires the "cvs" executable to be in the PATH
28  * of the system.
29  *
30  * @author Klaas Waslander
31  */

32 public class CvsSystemImpl implements ScmSystem {
33     public final static char REVISION_NAME_SEPARATOR = '_';
34     public final static char REVISION_VERSION_SEPARATOR = '-';
35
36     private ScmUrl url;
37     private String JavaDoc standardOutput;
38     private String JavaDoc errorOutput;
39     
40
41     /**
42      * Public default onstructor.
43      */

44     public CvsSystemImpl() {
45     }
46
47     public String JavaDoc getStandardOutput() {
48         return standardOutput;
49     }
50     public String JavaDoc getErrorOutput() {
51         return errorOutput;
52     }
53
54     /* (non-Javadoc)
55      * @see org.antmod.scm.ScmSystem#getUrl()
56      */

57     public ScmUrl getUrl() {
58         return url;
59     }
60
61     /* (non-Javadoc)
62      * @see org.antmod.scm.ScmSystem#setUrl(org.antmod.scm.ScmUrl)
63      */

64     public void setUrl(ScmUrl providerUrl) {
65         this.url = providerUrl;
66     }
67
68     public void doAdd(File file, boolean recursive) {
69         // check for parent "CVS" folder
70
File parentDir = file.getParentFile();
71         File parentCVSDir = new File(parentDir, "CVS");
72         boolean cvsDirCreated = false;
73         if (!parentCVSDir.exists()) {
74             // let's create CVS directory temporarily...
75
try {
76                 //
77
// IMPORTANT NOTE (Related to issue #36):
78
// When adding SystemUtils.LINE_SEPARATOR to these 3 CVS files
79
// the cvs client with cygwin and windows does not work at all.
80
// Removed addition of line separator, as it was not needed
81
//
82

83                 parentCVSDir.mkdir();
84
85                 File cvsRootFile = new File(parentCVSDir, "Root");
86                 FileUtils.touch(cvsRootFile);
87                 FileUtils.writeStringToFile(cvsRootFile, renderUrlToCvsRoot(getUrl()), SystemUtils.FILE_ENCODING);
88
89                 String JavaDoc reposString = ".";
90                 if (!StringUtils.isBlank(getUrl().getModule())) {
91                     reposString = getUrl().getModule();
92                 }
93                 File cvsReposFile = new File(parentCVSDir, "Repository");
94                 FileUtils.touch(cvsReposFile);
95                 FileUtils.writeStringToFile(cvsReposFile, reposString, SystemUtils.FILE_ENCODING);
96
97                 // empty Entries file, to prevent warning by cvs command
98
File cvsEntriesFile = new File(parentCVSDir, "Entries");
99                 FileUtils.touch(cvsEntriesFile);
100             } catch (IOException e) {
101                 throw new IllegalStateException JavaDoc("Creating CVS/ directory entries not possible: " + e);
102             }
103             cvsDirCreated = true;
104         }
105         
106         // recursively add
107
ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc(2);
108         cvsCommandList.add("add");
109         cvsCommandList.add(file.getName());
110         run(parentDir, cvsCommandList);
111         if (recursive) {
112             recursiveAdd(file);
113         }
114     }
115
116     // recursively add files in given dir to CVS, assuming dir itself has already been added
117
private void recursiveAdd(File parentDir) {
118         if (!parentDir.isDirectory()) {
119             return;
120         }
121         File[] files = parentDir.listFiles();
122         if (files != null) {
123             for (int i = 0; i < files.length; i++) {
124                 File childFile = files[i];
125                 if (!childFile.getName().equals("CVS")) {
126                     ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc(2);
127                     cvsCommandList.add("add");
128                     cvsCommandList.add(childFile.getName());
129                     run(parentDir, cvsCommandList);
130                     if (childFile.isDirectory()) {
131                         recursiveAdd(childFile);
132                     }
133                 }
134             }
135         }
136     }
137
138     /* (non-Javadoc)
139      * @see org.antmod.scm.ScmSystem#doCheckout(java.lang.String, java.lang.String, java.lang.String, boolean)
140      */

141     public void doCheckout(String JavaDoc moduleName, File destDir, ScmVersion version, boolean reallyQuiet) {
142         if (destDir == null) {
143             throw new IllegalArgumentException JavaDoc("destDir attribute for cvs checkout must not be null");
144         }
145         if (destDir.getParentFile() == null || !destDir.getParentFile().exists()) {
146             throw new IllegalArgumentException JavaDoc("destDir parent directory (basedir for the checkout) for cvs checkout does not exist on filesystem: " + destDir.getParentFile());
147         }
148         if (StringUtils.isBlank(moduleName)) {
149             throw new IllegalArgumentException JavaDoc("No modulename specified for CVS checkout to directory: " + destDir.getPath());
150         }
151
152         ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc();
153         if (reallyQuiet) {
154             cvsCommandList.add("-Q");
155         }
156         cvsCommandList.add("checkout");
157         cvsCommandList.add("-P");
158         cvsCommandList.add("-d");
159         cvsCommandList.add(destDir.getName());
160         addCvsRevisionCommand(version, cvsCommandList);
161         cvsCommandList.add(moduleName);
162
163         boolean suppressErrorOutput = reallyQuiet;
164         boolean suppressStandardOutput = reallyQuiet;
165         run(destDir.getParentFile(), cvsCommandList, suppressErrorOutput, suppressStandardOutput);
166         if (!suppressStandardOutput) {
167             this.standardOutput = null;
168         }
169     }
170
171     /* (non-Javadoc)
172      * @see org.antmod.scm.ScmSystem#doExport(java.lang.String, java.lang.String, java.lang.String, boolean)
173      */

174     public void doExport(String JavaDoc moduleName, File destDir, ScmVersion version, boolean reallyQuiet) {
175         if (destDir == null) {
176             throw new IllegalArgumentException JavaDoc("destDir attribute for cvs export must not be null");
177         }
178         if (destDir.getParentFile() == null || !destDir.getParentFile().exists()) {
179             throw new IllegalArgumentException JavaDoc("destDir parent directory (basedir for the export) for cvs export does not exist on filesystem: " + destDir.getParentFile());
180         }
181
182         //
183
// do the export
184
//
185
ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc();
186         if (reallyQuiet) {
187             cvsCommandList.add("-Q");
188         }
189         cvsCommandList.add("export");
190         cvsCommandList.add("-d ");
191         cvsCommandList.add(destDir.getName());
192
193         if (version == null || version.isTrunk()) {
194             // in export, a "-r" is always needed; handle that here
195
cvsCommandList.add("-r");
196             cvsCommandList.add("HEAD");
197         } else {
198             addCvsRevisionCommand(version, cvsCommandList);
199         }
200
201         cvsCommandList.add(moduleName);
202
203         boolean suppressErrorOutput = reallyQuiet;
204         boolean suppressStandardOutput = reallyQuiet;
205         run(destDir.getParentFile(), cvsCommandList, suppressErrorOutput, suppressStandardOutput);
206         if (!suppressStandardOutput) {
207             this.standardOutput = null;
208         }
209     }
210
211     public void doCheckoutOrUpdate(String JavaDoc packageName, File destDir, ScmVersion version, boolean reallyQuiet) {
212         if (isCheckoutDir(destDir)) {
213             doUpdate(packageName, destDir, version, reallyQuiet);
214         } else {
215             doCheckout(packageName, destDir, version, reallyQuiet);
216         }
217     }
218
219
220     public void doMerge(File moduleDir, ScmVersion version) {
221         doMerge(moduleDir, version, false);
222     }
223     public void doMerge(File moduleDir, ScmVersion version, boolean reallyQuiet) {
224         if (moduleDir == null) {
225             throw new IllegalArgumentException JavaDoc("moduleDir attribute for cvs merge must not be null");
226         }
227         if (!moduleDir.exists()) {
228             throw new IllegalArgumentException JavaDoc("moduleDir for cvs merge does not exist on filesystem: " + moduleDir.getPath());
229         }
230         ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc();
231         cvsCommandList.add("update");
232         cvsCommandList.add("-dP");
233         cvsCommandList.add("-j");
234         if (version == null || version.isTrunk()) {
235             cvsCommandList.add("HEAD");
236         } else {
237             cvsCommandList.add(version.getModuleName() + REVISION_NAME_SEPARATOR + version.toString(REVISION_VERSION_SEPARATOR));
238         }
239
240         // run merge, suppress output properly
241
boolean suppressErrorOutput = reallyQuiet;
242         boolean suppressStandardOutput = reallyQuiet;
243         if (moduleDir.isDirectory()) {
244             run(moduleDir, cvsCommandList, suppressErrorOutput, suppressStandardOutput);
245         } else {
246             cvsCommandList.add(moduleDir.getName());
247             run(moduleDir.getParentFile(), cvsCommandList, suppressErrorOutput, suppressStandardOutput);
248         }
249         if (!suppressStandardOutput) {
250             this.standardOutput = null;
251         }
252     }
253
254
255     public void doUpdate(File file, ScmVersion version) {
256         doUpdate(file.getName(), file, version, false);
257     }
258     public void doUpdate(String JavaDoc packageName, File file, ScmVersion version, boolean reallyQuiet) {
259         if (file == null) {
260             throw new IllegalArgumentException JavaDoc("file attribute for cvs update must not be null");
261         }
262         if (!file.exists()) {
263             throw new IllegalArgumentException JavaDoc("file for cvs update does not exist on filesystem: " + file.getPath());
264         }
265         ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc();
266         cvsCommandList.add("update");
267         cvsCommandList.add("-dP");
268         if (version != null) {
269             addCvsRevisionCommand(version, cvsCommandList);
270         }
271
272         boolean suppressErrorOutput = reallyQuiet;
273         boolean suppressStandardOutput = reallyQuiet;
274         if (file.isDirectory()) {
275             run(file, cvsCommandList, suppressErrorOutput, suppressStandardOutput);
276         } else {
277             cvsCommandList.add(file.getName());
278             run(file.getParentFile(), cvsCommandList, suppressErrorOutput, suppressStandardOutput);
279         }
280         /*
281         if (!reallyQuiet && !StringUtils.isBlank(resultOutput)) {
282             System.err.println(resultOutput.trim());
283             this.standardOutput = null;
284         }
285         */

286         if (!suppressStandardOutput) {
287             this.standardOutput = null;
288         }
289     }
290
291
292     /**
293      * Commit the given file or a while directory to CVS.
294      * @param file
295      */

296     public void doCommit(File file, String JavaDoc message) {
297         if (file == null) {
298             throw new IllegalArgumentException JavaDoc("file attribute for cvs commit must not be null");
299         }
300         if (message == null) {
301             throw new IllegalArgumentException JavaDoc("message attribute for cvs commit must not be null");
302         }
303
304         ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc();
305         cvsCommandList.add("commit");
306         cvsCommandList.add("-m");
307         cvsCommandList.add(message);
308         // REMIND: Klaas, Feb 2005: previously, spaces needed to be replaced, now probably this is not necessary anymore
309
//cvsCommandList.add(message.replace(' ', '_'));
310

311         // commit either whole directory, or just one file.
312
if (file.isDirectory()) {
313             run(file, cvsCommandList);
314         } else {
315             cvsCommandList.add(file.getName());
316             run(file.getParentFile(), cvsCommandList);
317         }
318     }
319
320     /**
321      * Returns the latest file revision.
322      */

323     public String JavaDoc getRevisionNumber(File file) {
324         if (file.isDirectory()) {
325             throw new IllegalArgumentException JavaDoc("File for 'getRevisionNumber' is a directory: " +file);
326         }
327
328         ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc();
329         cvsCommandList.add("status");
330         cvsCommandList.add(file.getName());
331         String JavaDoc status = run(file.getParentFile(), cvsCommandList);
332         String JavaDoc searchKey = "Working revision:";
333         int index = status.indexOf(searchKey);
334         if (index > 0) {
335             status = status.substring(index + searchKey.length()).trim();
336             int endIndex = Math.min(status.indexOf("\t"), status.indexOf(SystemUtils.LINE_SEPARATOR));
337             if (endIndex > 0) {
338                 return status.substring(0, endIndex).trim();
339             }
340         }
341         return null;
342     }
343
344     /**
345      * If the given module directory is not a tag, returns the latest version for that directory.
346      * @return null if no latest version is found
347      */

348     public ScmVersion getLatestVersion(File moduleDir) {
349         ScmVersion localVersion = getLocalVersion(moduleDir);
350         if (localVersion.isTag()) {
351             throw new RuntimeException JavaDoc("getLatestVersion is not possible on a cvs tag.");
352         }
353
354         if (!new File(moduleDir, "module.xml").exists()) {
355             throw new RuntimeException JavaDoc("FATAL: File module.xml does not exist in the module " + moduleDir.getName() + " !!!");
356         }
357
358         ScmVersion[] revs = getVersionsInBranch(new File(moduleDir, "module.xml"), localVersion);
359         if (revs.length > 0) {
360             return revs[0];
361         } else {
362             return null;
363         }
364     }
365
366     /**
367      * Returns the currently checked out version of the module in the given directory.
368      * @param moduleDir The directory where the module is currently checked out
369      * @return The current local version of the module
370      * @throws org.apache.tools.ant.BuildException
371      */

372     public ScmVersion getLocalVersion(File moduleDir) throws BuildException {
373         String JavaDoc localVersion = readTagString(moduleDir);
374         if (localVersion == null || localVersion.equals("HEAD")) {
375             localVersion = ScmVersion.VERSIONSTRING_TRUNK;
376         } else {
377             // strip until last "_", as that is separator between modulename and version
378
int lastUnderscore = localVersion.lastIndexOf("_");
379             if (lastUnderscore > 0) {
380                 localVersion = localVersion.substring(lastUnderscore + 1);
381             } else {
382                 throw new BuildException("Module " + moduleDir.getName() + " has invalid local version tag: " + localVersion);
383             }
384         }
385         return parseCvsRevision(moduleDir.getName(), localVersion);
386     }
387
388     /**
389      * Reads current CVS tag from the given module directory. Returns empty
390      * string if nothing could be read. [quickie version of local CVS status]
391      *
392      * @param moduleDir Module directory to read tag from
393      * @return CVS tag.
394      * @throws org.apache.tools.ant.BuildException If unable to read CVS tag.
395      */

396     private static String JavaDoc readTagString(File moduleDir) throws BuildException {
397         String JavaDoc tag = null;
398         try {
399             File fh = new File(moduleDir + File.separator + "CVS" + File.separator + "Tag");
400             if (fh.exists()) {
401                 BufferedReader rd = new BufferedReader(new FileReader(fh));
402                 rd.read();
403                 tag = rd.readLine();
404                 rd.close();
405             } else {
406                 //
407
// If "Tag" file does not exist,
408
// Let's read the "Entries" file and parse that to figure out the CSV tag.
409
fh = new File(moduleDir + File.separator + "CVS" + File.separator + "Entries");
410                 if (fh.exists()) {
411                     BufferedReader rd = new BufferedReader(new FileReader(fh));
412                     rd.read();
413
414                     // try each line
415
String JavaDoc searchFor = "/T" + moduleDir.getName();
416                     String JavaDoc line;
417                     while ((line = rd.readLine()) != null) {
418                         int searchForIndex = line.indexOf(searchFor);
419                         if (searchForIndex > 0) {
420                             tag = line.substring(searchForIndex + 2);
421                             break;
422                         }
423                     }
424                     rd.close();
425                 }
426             }
427         } catch (Exception JavaDoc e) {
428             throw new BuildException("Problem reading local tag: " + e);
429         }
430         return tag;
431     }
432
433     /**
434      * Returns all available versions for the given file in the given branch,
435      * with the newest number first and the oldest number last (oldest is usually the ".0" version).
436      */

437     public ScmVersion[] getVersionsInBranch(File file, ScmVersion branch) {
438         if (file == null) {
439             throw new IllegalArgumentException JavaDoc("File attribute for cvs revisions must not be null");
440         }
441         String JavaDoc branchName = renderCvsRevision(branch);
442
443         // do two digit versions?
444
boolean twoDigit = false;
445         if (branch == null || branch.isTrunk()) {
446             // 2 digit versions only
447
twoDigit = true;
448         }
449
450         ArrayList JavaDoc result = new ArrayList JavaDoc();
451
452         //
453
// get cvs output and PARSE it
454
//
455
File moduleFile = file.getParentFile();
456         ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc(3);
457         cvsCommandList.add("status");
458         cvsCommandList.add("-v");
459         cvsCommandList.add(file.getName());
460         String JavaDoc cvsResult = run(moduleFile, cvsCommandList);
461         try {
462             BufferedReader reader = new BufferedReader(new StringReader(cvsResult));
463             String JavaDoc line;
464             boolean started = false; // started reading tags already?
465
while ((line = reader.readLine()) != null) {
466                 if (started) {
467                     //System.err.println("Consider line: " + line);
468
if (line.trim().length() > 0) {
469                         // let's see if we need to add this tag...
470
line = line.trim();
471                         int tabIndex = line.indexOf("\t");
472                         if (tabIndex > 0) {
473                             line = line.substring(0, tabIndex).trim();
474                         }
475                         //System.err.println(branchName + " POTENTIAL TAG FOUND: \"" + line + "\"");
476

477                         // tagname must start with the name of this module
478
if (line.startsWith(file.getParentFile().getName()+REVISION_NAME_SEPARATOR)) {
479                             if (twoDigit) {
480                                 //System.err.println(branchName + " TWO DIGIT " + countVersionChars(REVISION_VERSION_SEPARATOR, line));
481
if (countVersionChars(REVISION_VERSION_SEPARATOR, line) == 1) {
482                                     result.add(parseCvsRevision(moduleFile.getName(), line));
483                                 }
484                             } else {
485                                 //System.err.println("startswith: " + line.trim().startsWith(branchName) + ", COUNTCHARS:" + countVersionChars(REVISION_VERSION_SEPARATOR, line));
486
// only add versions starting with branch name
487
if (line.trim().startsWith(branchName) && countVersionChars(REVISION_VERSION_SEPARATOR, line) > 1) {
488                                     //System.err.println(" ADD 3 digit TAG!!!");
489
result.add(parseCvsRevision(moduleFile.getName(), line));
490                                 }
491                             }
492                         }
493                     } else {
494                         //System.err.println("BAILOUT ON LINE: " + line);
495
// we are past the last tag, let's bail out
496
//break;
497
}
498                 }
499
500                 // check whether to start with parsing versions at the next line
501
if (line.toLowerCase().indexOf("existing tags") >= 0) {
502                     started = true;
503                 }
504             }
505
506         } catch (IOException ioe) {
507             ioe.printStackTrace();
508         }
509
510         Collections.sort(result);
511
512         ScmVersion[] array = new ScmVersion[result.size()];
513         result.toArray(array);
514         return array;
515     }
516
517     /**
518      * Implementation of the ScmDifference interface for returning cvs diff entries in this class.
519      * @author Klaas Waslander
520      */

521     private static class ScmDifferenceImpl implements ScmDifference {
522         String JavaDoc filename;
523         boolean conflict = false;
524         StringBuffer JavaDoc log = new StringBuffer JavaDoc();
525
526         ScmDifferenceImpl(String JavaDoc filename) {
527             this.filename = filename;
528         }
529         public String JavaDoc getFilename() {
530             return filename;
531         }
532         public boolean hasConflict() {
533             return conflict;
534         }
535         private void setConflict(boolean conflict) {
536             this.conflict = conflict;
537         }
538         public String JavaDoc getLog() {
539             return log.toString();
540         }
541         private void addLogLine(String JavaDoc logLine) {
542             this.log.append(logLine);
543             this.log.append(HexDump.EOL);
544         }
545     }
546     
547     /**
548      * Check whether the given checkout directory is up-to-date
549      * when comparing it to the repository contents.
550      * @param checkoutDir The directory with locally checked out contents
551      * @return Whether the checkoutDir is up-to-date
552      */

553     public boolean isUpToDate(File checkoutDir) {
554         //
555
// get cvs output and PARSE it
556
//
557
ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc();
558         cvsCommandList.add("-Q");
559         cvsCommandList.add("status");
560         String JavaDoc cvsResult = run(checkoutDir, cvsCommandList);
561         try {
562             BufferedReader reader = new BufferedReader(new StringReader(cvsResult));
563             String JavaDoc line;
564
565             while ((line = reader.readLine()) != null) {
566                 if (line.startsWith("File:")) {
567                     int statusIndex = line.indexOf("Status:");
568                     if (statusIndex < 0) {
569                         throw new IllegalStateException JavaDoc("Every cvs-status line should contain 'Status:', but this line doesn't? \"" + line + "\"");
570                     }
571                     String JavaDoc statusString = line.substring(statusIndex + 7).trim();
572                     if (!statusString.equals("Up-to-date") && !statusString.equals("Unknown")) {
573                         return false;
574                     }
575                 }
576             }
577         } catch (IOException ioe) {
578             ioe.printStackTrace();
579         }
580         return true;
581     }
582
583     /**
584      * Returns the files that have changed between the two given cvs revisions.
585      */

586     public ScmDifference[] getDifferences(ScmVersion version1, ScmVersion version2) {
587         if (version1 .getModuleName() == null) {
588             throw new IllegalArgumentException JavaDoc("Modulename attribute (of version1) for cvsdiffs must not be null");
589         }
590         if (version2.getModuleName() == null) {
591             throw new IllegalArgumentException JavaDoc("Modulename attribute (of version2) for cvsdiffs must not be null");
592         }
593         if (!version1.getModuleName().equals(version2.getModuleName())) {
594             throw new IllegalArgumentException JavaDoc("Module of version1 \"" + version1.getModuleName() + "\" is not the same as module of version2 \"" + version2.getModuleName() + "\"");
595         }
596
597         String JavaDoc cvsRev1 = renderCvsRevision(version1);
598         if (version1.isTrunk()) {
599             cvsRev1 = "HEAD";
600         }
601         String JavaDoc cvsRev2 = renderCvsRevision(version2);
602         if (version2.isTrunk()) {
603             cvsRev2 = "HEAD";
604         }
605
606         ArrayList JavaDoc result = new ArrayList JavaDoc();
607
608         //
609
// get cvs output and PARSE it
610
//
611
ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc();
612         cvsCommandList.add("rdiff");
613         cvsCommandList.add("-R");
614         cvsCommandList.add("-r");
615         cvsCommandList.add(cvsRev1);
616         cvsCommandList.add("-r");
617         cvsCommandList.add(cvsRev2);
618         cvsCommandList.add(version1.getModuleName());
619         String JavaDoc cvsResult = run(null, cvsCommandList);
620         try {
621             BufferedReader reader = new BufferedReader(new StringReader(cvsResult));
622             String JavaDoc line;
623             ScmDifferenceImpl currentEntry = null;
624
625             while ((line = reader.readLine()) != null) {
626                 if (line.startsWith("Index:")) {
627                     // strip off "Index:"
628
String JavaDoc file = line.substring(7).trim();
629                     // strip off module name
630
file = file.substring(version1.getModuleName().length() + 1);
631                     // add diff entry object
632
currentEntry = new ScmDifferenceImpl(file);
633                     result.add(currentEntry);
634
635                 } else if (currentEntry != null) {
636                     currentEntry.addLogLine(line);
637
638                     if (line.startsWith("! ")) {
639                         currentEntry.setConflict(true);
640                     }
641                 }
642             }
643         } catch (IOException ioe) {
644             ioe.printStackTrace();
645         }
646
647         ScmDifference[] array = new ScmDifference[result.size()];
648         result.toArray(array);
649         return array;
650     }
651
652     /**
653      * Creates a new branch in the HEAD of the given module.
654      */

655     public String JavaDoc createBranchInTrunk(ScmVersion newBranchForModule) {
656         if (newBranchForModule == null) {
657             throw new IllegalArgumentException JavaDoc("newBranchForModule attribute for createBranchInTrunk must not be null");
658         }
659         ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc();
660         cvsCommandList.add("rtag");
661         cvsCommandList.add("-b");
662         cvsCommandList.add("-R");
663         cvsCommandList.add(renderCvsRevision(newBranchForModule));
664         cvsCommandList.add(newBranchForModule.getModuleName());
665         //return run(null, "rtag -b -R " + renderCvsRevision(newBranchForModule) + " " + newBranchForModule.getModuleName());
666
return run(null, cvsCommandList);
667     }
668
669     /**
670      * Creates a new tag in the given BRANCH of the given module.
671      */

672     public String JavaDoc createTagInBranch(ScmVersion existingBranch, ScmVersion newTag) {
673         if (existingBranch == null) {
674             throw new IllegalArgumentException JavaDoc("existingBranch attribute for createTagInBranch must not be null");
675         }
676         if (newTag == null) {
677             throw new IllegalArgumentException JavaDoc("newTag attribute for createTagInBranch must not be null");
678         }
679         if (existingBranch.getModuleName() == null) {
680             throw new IllegalArgumentException JavaDoc("moduleName of existing branch for createTagInBranch must not be null");
681         }
682         ArrayList JavaDoc cvsCommandList = new ArrayList JavaDoc();
683         cvsCommandList.add("rtag");
684         cvsCommandList.add("-R");
685         cvsCommandList.add("-r");
686         cvsCommandList.add(renderCvsRevision(existingBranch));
687         cvsCommandList.add(renderCvsRevision(newTag));
688         cvsCommandList.add(existingBranch.getModuleName());
689         //return run(null, "rtag -R -r " + renderCvsRevision(existingBranch) + " " + renderCvsRevision(newTag) + " " + existingBranch.getModuleName());
690
return run(null, cvsCommandList);
691     }
692
693
694     /**
695      * Utility method for counting the number of given characters in the given string.
696      */

697     static int countVersionChars(char c, String JavaDoc s) {
698         // first strip off modulename
699
int lastUnderscore = s.lastIndexOf("_");
700         if (lastUnderscore > 0) {
701             s = s.substring(lastUnderscore + 1);
702         }
703
704         // next count the occurences of char c in string s
705
return StringUtils.countMatches(s, String.valueOf(c));
706     }
707
708     /**
709      * Runs the given cvs command in the given directory, and returns standard output!
710      * @param baseDir
711      * @param command
712      * @return
713      */

714     private String JavaDoc run(File baseDir, ArrayList JavaDoc commandList) {
715         return run(baseDir, commandList, false);
716     }
717
718     private String JavaDoc run(File baseDir, ArrayList JavaDoc commandList, boolean suppressErrorOutput) {
719         return run(baseDir, commandList, suppressErrorOutput, true);
720     }
721
722     /**
723      * Runs the given cvs command in the given directory, and returns standard output!
724      * @param baseDir
725      * @param command
726      * @return
727      */

728     private String JavaDoc run(File baseDir, ArrayList JavaDoc commandList, boolean suppressErrorOutput, final boolean suppressStandardOutput) {
729         // work with copy for local changes
730
commandList = new ArrayList JavaDoc(commandList);
731         ArrayList JavaDoc orgCommandList = new ArrayList JavaDoc(commandList);
732
733         // make it quiet if not done already
734
if (commandList.indexOf("-q") < 0 && commandList.indexOf("-Q") < 0) {
735             commandList.add(0, "-q");
736         }
737         // add CVS root
738
commandList.add(0, "-d");
739         commandList.add(1, renderUrlToCvsRoot(getUrl()));
740
741         // of course, prepend the "cvs" executable to invoke
742
commandList.add(0, AntmodProperties.getProperty("antmod.scm.cvs.executable"));
743
744         // create launcher
745
ProcessLauncher launcher = new ProcessLauncher(commandList, baseDir);
746
747         final StringBuffer JavaDoc stdOut = new StringBuffer JavaDoc();
748         final StringBuffer JavaDoc stdErr = new StringBuffer JavaDoc();
749         stdOut.setLength(0);
750         stdErr.setLength(0);
751         launcher.addOutputListener(new ProcessLauncher.OutputListener() {
752             public void standardOutput(char[] output) {
753                 stdOut.append(output);
754
755                 if (!suppressStandardOutput) {
756                     System.err.print(output);
757                 }
758             }
759
760             public void errorOutput(char[] output) {
761                 stdErr.append(output);
762             }
763         });
764
765         // launch and wait until done...
766
launcher.launch();
767
768         // if there is error output, log it for now
769
if (!suppressErrorOutput && stdErr.length() > 0) {
770             //System.err.println("CVS command 'cvs " + command + "' produced error output:");
771
System.err.println(stdErr.toString());
772         }
773
774         // return standard output
775
this.standardOutput = stdOut.toString();
776         this.errorOutput = stdErr.toString();
777         return stdOut.toString();
778     }
779
780     
781     /*
782     private String run(File baseDir, String command) {
783         return run(baseDir, command, false);
784     }
785
786     private String run(File baseDir, String command, boolean reallyQuiet) {
787         // make it quiet if not done already
788         if (command.indexOf("-q") < 0 && command.indexOf("-Q") < 0) {
789             command = "-q " + command;
790         }
791         // add CVS root
792         command = "-d " + renderUrlToCvsRoot(getUrl()) + " " + command;
793
794         // create launcher
795         ProcessLauncher launcher = new ProcessLauncher(AntmodProperties.getProperty("antmod.scm.cvs.executable") + " " + command, baseDir);
796
797         final StringBuffer stdOut = new StringBuffer();
798         final StringBuffer stdErr = new StringBuffer();
799         stdOut.setLength(0);
800         stdErr.setLength(0);
801         launcher.addOutputListener(new ProcessLauncher.OutputListener() {
802             public void standardOutput(char[] output) {
803                 stdOut.append(output);
804             }
805
806             public void errorOutput(char[] output) {
807                 stdErr.append(output);
808             }
809         });
810
811         // launch and wait until done...
812         launcher.launch();
813
814         // if there is error output, log it for now
815         if (!reallyQuiet && stdErr.length() > 0) {
816             //System.err.println("CVS command 'cvs " + command + "' produced error output:");
817             System.err.println(stdErr.toString());
818         }
819
820         // return standard output
821         this.standardOutput = stdOut.toString();
822         this.errorOutput = stdErr.toString();
823         return stdOut.toString();
824     }
825 */

826
827     static ScmVersion parseCvsRevision(String JavaDoc moduleName, String JavaDoc versionString) {
828         // parse the version string
829
int major = -1;
830         int minor = -1;
831         int patch = -1;
832         if (versionString != null && !versionString.trim().equalsIgnoreCase("HEAD") && !versionString.trim().equalsIgnoreCase(ScmVersion.VERSIONSTRING_TRUNK)) {
833             int startversionIndex = versionString.lastIndexOf(REVISION_NAME_SEPARATOR);
834             if (startversionIndex < 0) {
835                 // no modulename in version string
836
startversionIndex = -1;
837             }
838
839             int dashIndex = versionString.indexOf(REVISION_VERSION_SEPARATOR, startversionIndex + 1);
840             major = Integer.parseInt(versionString.substring(startversionIndex + 1, dashIndex));
841
842             int secondDashIndex = versionString.indexOf(REVISION_VERSION_SEPARATOR, dashIndex + 1);
843             if (secondDashIndex > 0) {
844                 minor = Integer.parseInt(versionString.substring(dashIndex + 1, secondDashIndex));
845                 patch = Integer.parseInt(versionString.substring(secondDashIndex + 1));
846             } else {
847                 minor = Integer.parseInt(versionString.substring(dashIndex + 1));
848             }
849         }
850
851         return new ScmVersion(moduleName, major, minor, patch);
852     }
853
854     static String JavaDoc renderCvsRevision(ScmVersion ver) {
855         if (ver == null) {
856             return ScmVersion.VERSIONSTRING_TRUNK;
857         }
858         if (ver.getModuleName() == null || ver.getModuleName().trim().length() == 0) {
859             throw new RuntimeException JavaDoc("Modulename unknown - cvs revision string not possible.");
860         }
861         if (!ver.isTrunk()) {
862             return ver.getModuleName() + REVISION_NAME_SEPARATOR + ver.toString(REVISION_VERSION_SEPARATOR);
863         } else {
864             return ver.toString();
865         }
866     }
867
868     static String JavaDoc renderUrlToCvsRoot(ScmUrl url) {
869         // TODO: password support not tested yet!
870
StringBuffer JavaDoc cvsRoot = new StringBuffer JavaDoc();
871         if (url.getProtocol() != null) {
872             cvsRoot.append(":");
873             cvsRoot.append(url.getProtocol());
874             cvsRoot.append(":");
875         }
876         if (url.getUser() != null) {
877             cvsRoot.append(url.getUser());
878             if (url.getPassword() != null) {
879                 cvsRoot.append(":");
880                 cvsRoot.append(url.getPassword());
881             }
882             if (url.getHost() != null) {
883                 cvsRoot.append("@");
884                 cvsRoot.append(url.getHost());
885             }
886             cvsRoot.append(":");
887         }
888         cvsRoot.append(url.getPath());
889
890         return cvsRoot.toString();
891     }
892
893     /**
894      * @deprecated Use addCvsRevisionCommand instead
895      */

896     static String JavaDoc constructCvsRevisionCommand(ScmVersion version) {
897         if (version == null || version.isTrunk()) {
898             return "-A";
899         } else {
900             // prepend module name if needed
901
return "-r " + version.getModuleName() + REVISION_NAME_SEPARATOR + version.toString(REVISION_VERSION_SEPARATOR);
902         }
903     }
904     /**
905      * Constructs the correct Cvs command line options for a module's revision.
906      * This is useful for Cvs checkout and update commands.
907      * @param packageName
908      * @param revision
909      * @return
910      */

911     static void addCvsRevisionCommand(ScmVersion version, ArrayList JavaDoc commandList) {
912         if (version == null || version.isTrunk()) {
913             commandList.add("-A");
914         } else {
915             // prepend module name if needed
916
commandList.add("-r");
917             commandList.add(version.getModuleName() + REVISION_NAME_SEPARATOR + version.toString(REVISION_VERSION_SEPARATOR));
918         }
919     }
920
921     public boolean isCheckoutDir(File directory) {
922         return new File(directory, "CVS").exists();
923     }
924 }
925
Popular Tags