Source Code Cross Referenced for SvnSystemImpl.java in  » Build » antmod » org » antmod » scm » impl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Build » antmod » org.antmod.scm.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package org.antmod.scm.impl;
0002:
0003:        import java.io.BufferedReader;
0004:        import java.io.File;
0005:        import java.io.IOException;
0006:        import java.io.StringReader;
0007:        import java.util.ArrayList;
0008:        import java.util.Collections;
0009:        import java.util.StringTokenizer;
0010:
0011:        import org.antmod.conf.AntmodProperties;
0012:        import org.antmod.scm.ScmDifference;
0013:        import org.antmod.scm.ScmSystem;
0014:        import org.antmod.scm.ScmUrl;
0015:        import org.antmod.scm.ScmVersion;
0016:        import org.antmod.util.ProcessLauncher;
0017:        import org.apache.commons.io.FileUtils;
0018:        import org.apache.commons.io.HexDump;
0019:        import org.apache.commons.lang.StringUtils;
0020:        import org.apache.tools.ant.BuildException;
0021:
0022:        /**
0023:         * Subversion repository provider, providing access to this
0024:         * compelling Source Configuration Management alternative for CVS.
0025:         * <p/>
0026:         * This Subversion repository provider is a thin layer on top
0027:         * of the "svn" commandline executable, and as such
0028:         * requires the "svn" executable to be in the PATH
0029:         * of the system.
0030:         * 
0031:         * @author Klaas Waslander
0032:         */
0033:        public class SvnSystemImpl implements  ScmSystem {
0034:
0035:            public final static char REVISION_NAME_SEPARATOR = '_';
0036:            public final static char REVISION_VERSION_SEPARATOR = '.';
0037:
0038:            private ScmUrl url;
0039:            private String standardOutput;
0040:            private String errorOutput;
0041:
0042:            /**
0043:             * Public default onstructor.
0044:             */
0045:            public SvnSystemImpl() {
0046:            }
0047:
0048:            public String getStandardOutput() {
0049:                return standardOutput;
0050:            }
0051:
0052:            public String getErrorOutput() {
0053:                return errorOutput;
0054:            }
0055:
0056:            /* (non-Javadoc)
0057:             * @see org.antmod.scm.ScmSystem#getUrl()
0058:             */
0059:            public ScmUrl getUrl() {
0060:                return url;
0061:            }
0062:
0063:            /* (non-Javadoc)
0064:             * @see org.antmod.scm.ScmSystem#setUrl(org.antmod.scm.ScmUrl)
0065:             */
0066:            public void setUrl(ScmUrl providerUrl) {
0067:                this .url = providerUrl;
0068:            }
0069:
0070:            /**
0071:             * Imports given file into Subversion, with recursivity either on or off.
0072:             * @param file The file/directory to be imported
0073:             * @param recursive Whether to recurse into subdirectories, if any.
0074:             */
0075:            private void doImport(File file, boolean recursive) {
0076:                if (!file.isDirectory()) {
0077:                    throw new IllegalArgumentException(
0078:                            "Cannot import a file, it needs to be a directory: "
0079:                                    + file.getPath());
0080:                }
0081:                ArrayList svnCommand = new ArrayList();
0082:
0083:                String creationMessage = "Creation of new module "
0084:                        + file.getName();
0085:                String svnModulePath = renderUrlToSvnArg(getUrl()) + '/'
0086:                        + file.getName();
0087:
0088:                // create import command for adding to repository
0089:                svnCommand.add("import");
0090:                addAuthenticationArgs(svnCommand);
0091:                svnCommand.add("-m");
0092:                svnCommand.add(creationMessage);
0093:                if (!recursive) {
0094:                    svnCommand.add("--non-recursive");
0095:                }
0096:                svnCommand.add(".");
0097:                svnCommand.add(svnModulePath + "/trunk");
0098:
0099:                // run import command in the same directory
0100:                run(file, svnCommand);
0101:
0102:                // create initial tags and branches directory in repository
0103:                svnCommand = new ArrayList();
0104:                svnCommand.add("mkdir");
0105:                addAuthenticationArgs(svnCommand);
0106:                svnCommand.add("-m");
0107:                svnCommand.add(creationMessage);
0108:                svnCommand.add(svnModulePath + "/branches");
0109:                run(null, svnCommand);
0110:
0111:                svnCommand.set(svnCommand.size() - 1, svnModulePath + "/tags");
0112:                run(null, svnCommand);
0113:            }
0114:
0115:            public void doAdd(File file, boolean recursive) {
0116:                // check for parent ".svn" folder
0117:                File parentDir = file.getParentFile();
0118:
0119:                if (!isCheckoutDir(parentDir)) {
0120:                    // silently switch to importing...
0121:                    doImport(file, recursive);
0122:                } else {
0123:                    // recursively add, 'recursive' flag ignored!
0124:                    ArrayList svnCommand = new ArrayList();
0125:                    svnCommand.add("add");
0126:                    svnCommand.add(file.getName());
0127:                    run(parentDir, svnCommand);
0128:                }
0129:            }
0130:
0131:            /**
0132:             * Implements Subversion checkout of a module.
0133:             */
0134:            public void doCheckout(String moduleName, File destDir,
0135:                    ScmVersion version, boolean reallyQuiet) {
0136:                doSvnRetrieve("checkout", moduleName, destDir, version,
0137:                        reallyQuiet);
0138:            }
0139:
0140:            /**
0141:             * Implements Subversion export of a module.
0142:             */
0143:            public void doExport(String moduleName, File destDir,
0144:                    ScmVersion version, boolean reallyQuiet) {
0145:                doSvnRetrieve("export", moduleName, destDir, version,
0146:                        reallyQuiet);
0147:            }
0148:
0149:            public void doCheckoutOrUpdate(String packageName, File destDir,
0150:                    ScmVersion version, boolean reallyQuiet) {
0151:                if (isCheckoutDir(destDir)) {
0152:                    doUpdate(packageName, destDir, version, reallyQuiet);
0153:                } else {
0154:                    doCheckout(packageName, destDir, version, reallyQuiet);
0155:                }
0156:            }
0157:
0158:            private void doSvnRetrieve(String svnCommandName,
0159:                    String moduleName, File destDir, ScmVersion version,
0160:                    boolean reallyQuiet) {
0161:                if (destDir == null) {
0162:                    throw new IllegalArgumentException(
0163:                            "destDir attribute for Subversion "
0164:                                    + svnCommandName + " must not be null");
0165:                }
0166:                if (destDir.getParentFile() == null
0167:                        || !destDir.getParentFile().exists()) {
0168:                    throw new IllegalArgumentException(
0169:                            "destDir parent directory (basedir for the "
0170:                                    + svnCommandName + ") for Subversion "
0171:                                    + svnCommandName
0172:                                    + " does not exist on filesystem: "
0173:                                    + destDir.getParentFile());
0174:                }
0175:
0176:                ArrayList svnCommand = new ArrayList();
0177:                svnCommand.add(svnCommandName);
0178:
0179:                // add authentication tokens...		
0180:                addAuthenticationArgs(svnCommand);
0181:
0182:                // checkout proper module and version
0183:                svnCommand.add(renderUrlToSvnArg(getUrl()) + '/'
0184:                        + renderSvnPath(moduleName, version));
0185:
0186:                // checkout in the proper target directory locally
0187:                svnCommand.add(destDir.getName());
0188:
0189:                boolean suppressErrorOutput = reallyQuiet;
0190:                boolean suppressStandardOutput = reallyQuiet;
0191:                //String output =
0192:                run(destDir.getParentFile(), svnCommand, suppressErrorOutput,
0193:                        suppressStandardOutput);
0194:                /*
0195:                if (!reallyQuiet && !StringUtils.isBlank(output)) {
0196:                	System.err.println(output.trim());
0197:                	this.standardOutput = null;
0198:                }
0199:                 */
0200:                if (!suppressStandardOutput) {
0201:                    this .standardOutput = null;
0202:                }
0203:            }
0204:
0205:            /**
0206:             * Internal utility to add username, password and non-interactive flags
0207:             * to the svn commandline in the given stringbuffer.
0208:             */
0209:            private void addAuthenticationArgs(ArrayList list) {
0210:                // add authentication parameters if any...      
0211:                if (getUrl().getUser() != null) {
0212:                    list.add("--username");
0213:                    list.add(getUrl().getUser());
0214:                }
0215:                if (getUrl().getPassword() != null) {
0216:                    list.add("--password");
0217:                    list.add(getUrl().getPassword());
0218:
0219:                    // non-interactive option of svn checkout command, only if password is known!!!
0220:                    list.add("--non-interactive");
0221:                }
0222:
0223:            }
0224:
0225:            public void doMerge(File moduleDir, ScmVersion version) {
0226:                doMerge(moduleDir, version, false);
0227:            }
0228:
0229:            public void doMerge(File moduleDir, ScmVersion version,
0230:                    boolean reallyQuiet) {
0231:                if (moduleDir == null) {
0232:                    throw new IllegalArgumentException(
0233:                            "moduleDir attribute for Subversion merge must not be null");
0234:                }
0235:                if (!moduleDir.exists()) {
0236:                    throw new IllegalArgumentException(
0237:                            "moduleDir for Subversion merge does not exist on filesystem: "
0238:                                    + moduleDir.getPath());
0239:                }
0240:                if (!isCheckoutDir(moduleDir)) {
0241:                    throw new IllegalArgumentException("Directory "
0242:                            + moduleDir.getPath()
0243:                            + " is not an existing Subversion checkout.");
0244:                }
0245:                ScmVersion localVersion = getLocalVersion(moduleDir);
0246:
0247:                ArrayList svnCommand = new ArrayList();
0248:                svnCommand.add("merge");
0249:
0250:                // add authentication tokens...		
0251:                addAuthenticationArgs(svnCommand);
0252:
0253:                // add the two versions which are different
0254:                svnCommand.add(renderUrlToSvnArg(getUrl()) + '/'
0255:                        + renderSvnPath(moduleDir.getName(), localVersion));
0256:                svnCommand.add(renderUrlToSvnArg(getUrl()) + '/'
0257:                        + renderSvnPath(moduleDir.getName(), version));
0258:
0259:                // run the merge
0260:                boolean suppressErrorOutput = reallyQuiet;
0261:                boolean suppressStandardOutput = reallyQuiet;
0262:                run(moduleDir, svnCommand, suppressErrorOutput,
0263:                        suppressStandardOutput);
0264:                if (!suppressStandardOutput) {
0265:                    this .standardOutput = null;
0266:                }
0267:            }
0268:
0269:            public void doUpdate(File file, ScmVersion version) {
0270:                doUpdate(file.getName(), file, version, false);
0271:            }
0272:
0273:            /** this method not yet exposed yet */
0274:            private void doUpdate(String packageName, File file,
0275:                    ScmVersion version, boolean reallyQuiet) {
0276:                if (file == null) {
0277:                    throw new IllegalArgumentException(
0278:                            "file attribute for Subversion update must not be null");
0279:                }
0280:                if (!file.exists()) {
0281:                    throw new IllegalArgumentException(
0282:                            "file for Subversion update does not exist on filesystem: "
0283:                                    + file.getPath());
0284:                }
0285:                if (!isCheckoutDir(file)) {
0286:                    throw new IllegalArgumentException("Directory "
0287:                            + file.getPath()
0288:                            + " is not an existing Subversion checkout.");
0289:                }
0290:
0291:                // check whether the proper SVN url is checked out currently...
0292:                String currentCheckoutUrl = readCheckoutUrl(file);
0293:                boolean differentUrl = false;
0294:                if (currentCheckoutUrl != null
0295:                        && (currentCheckoutUrl.indexOf(this .url.getPath()) < 0 || (this .url
0296:                                .getHost() != null && currentCheckoutUrl
0297:                                .indexOf(this .url.getHost()) < 0))) {
0298:                    differentUrl = true;
0299:                }
0300:
0301:                // check whether local version changed
0302:                ScmVersion localVersion = null;
0303:                boolean differentVersion = false;
0304:                if (version != null) {
0305:                    localVersion = getLocalVersion(version.getModuleName(),
0306:                            file);
0307:                    if (localVersion == null) {
0308:                        throw new IllegalStateException(
0309:                                "Local version of \""
0310:                                        + file.getName()
0311:                                        + "\" unknown! Most likely it is an invalid Subversion checkout.");
0312:                    }
0313:                    if (!version.equals(localVersion)) {
0314:                        differentVersion = true;
0315:                    }
0316:                }
0317:
0318:                // switch to proper version or url if needed
0319:                if (differentVersion || differentUrl) {
0320:                    // if no local changes, remove existing checkout and replace with new one
0321:                    String localSvnChanges = getLocalSvnChanges(file);
0322:                    if (!StringUtils.isBlank(localSvnChanges)) {
0323:                        if (differentVersion) {
0324:                            System.err
0325:                                    .println("Subversion update from version "
0326:                                            + localVersion
0327:                                            + " to "
0328:                                            + version
0329:                                            + " not possible because of local changes:");
0330:                        } else {
0331:                            System.err
0332:                                    .println("Subversion update from url "
0333:                                            + currentCheckoutUrl
0334:                                            + " to "
0335:                                            + renderUrlToSvnArg(this .url)
0336:                                            + " not possible because of local changes:");
0337:                        }
0338:                        System.err.println(localSvnChanges);
0339:                        this .errorOutput = null;
0340:                        return;
0341:                    } else {
0342:                        if (differentVersion) {
0343:                            System.err
0344:                                    .println("Changing existing checkout of \""
0345:                                            + file.getName()
0346:                                            + "\" from version \""
0347:                                            + localVersion + "\" to \""
0348:                                            + version + "\"");
0349:                        } else {
0350:                            System.err
0351:                                    .println("Changing existing checkout of \""
0352:                                            + file.getName() + "\" from url \""
0353:                                            + currentCheckoutUrl + "\" to \""
0354:                                            + renderUrlToSvnArg(this .url)
0355:                                            + "\"");
0356:                        }
0357:
0358:                        // remove existing checkout, by cleaning module directory
0359:                        deleteSvnFilesInDirectory(file);
0360:
0361:                        // checkout new version
0362:                        doCheckout(packageName, file, version, reallyQuiet);
0363:                        return;
0364:                    }
0365:                }
0366:
0367:                // continue with svn update
0368:                ArrayList svnCommand = new ArrayList();
0369:                svnCommand.add("update");
0370:
0371:                // add authentication tokens...		
0372:                addAuthenticationArgs(svnCommand);
0373:
0374:                boolean suppressErrorOutput = reallyQuiet;
0375:                boolean suppressStandardOutput = reallyQuiet;
0376:                if (file.isDirectory()) {
0377:                    run(file, svnCommand, suppressErrorOutput,
0378:                            suppressStandardOutput);
0379:                } else {
0380:                    svnCommand.add(file.getName());
0381:                    run(file.getParentFile(), svnCommand, suppressErrorOutput,
0382:                            suppressStandardOutput);
0383:                }
0384:                /*
0385:                if (!reallyQuiet && !StringUtils.isBlank(resultOutput)) {
0386:                	System.err.println(resultOutput.trim());
0387:                	this.standardOutput = null;
0388:                }
0389:                 */
0390:                if (!suppressStandardOutput) {
0391:                    this .standardOutput = null;
0392:                }
0393:            }
0394:
0395:            private void deleteSvnFilesInDirectory(File dir) {
0396:                // list svn files
0397:                ArrayList svnCommand = new ArrayList(1);
0398:                svnCommand.add("list");
0399:                String svnResult = run(dir, svnCommand);
0400:                StringTokenizer st = new StringTokenizer(svnResult, "\n");
0401:                while (st.hasMoreTokens()) {
0402:                    File moduleFile = new File(dir, st.nextToken().trim());
0403:                    if (moduleFile.exists()) {
0404:                        if (moduleFile.isDirectory()) {
0405:                            try {
0406:                                FileUtils.deleteDirectory(moduleFile);
0407:                            } catch (IOException e) {
0408:                                e.printStackTrace();
0409:                            }
0410:                        } else {
0411:                            moduleFile.delete();
0412:                        }
0413:                    }
0414:                }
0415:
0416:                // delete the ".svn" folder
0417:                try {
0418:                    FileUtils.deleteDirectory(new File(dir, ".svn"));
0419:                } catch (IOException e) {
0420:                    e.printStackTrace();
0421:                }
0422:            }
0423:
0424:            /**
0425:             * Commit the given file or a while directory to Subversion.
0426:             * @param file
0427:             */
0428:            public void doCommit(File file, String message) {
0429:                if (file == null) {
0430:                    throw new IllegalArgumentException(
0431:                            "file attribute for Subversion commit must not be null");
0432:                }
0433:                if (message == null) {
0434:                    throw new IllegalArgumentException(
0435:                            "message attribute for Subversion commit must not be null");
0436:                }
0437:
0438:                if (!isCheckoutDir(file)) {
0439:                    System.err.println("Nothing to commit in \""
0440:                            + file.getPath()
0441:                            + "\", it is not an svn working copy.");
0442:                    return;
0443:                }
0444:
0445:                ArrayList svnCommand = new ArrayList();
0446:                svnCommand.add("commit");
0447:
0448:                // add authentication arguments...
0449:                addAuthenticationArgs(svnCommand);
0450:
0451:                // message...
0452:                svnCommand.add("-m");
0453:                svnCommand.add(message);
0454:
0455:                // commit either whole directory, or just one file.
0456:                if (file.isDirectory()) {
0457:                    run(file, svnCommand);
0458:                } else {
0459:                    svnCommand.add(file.getName());
0460:                    run(file.getParentFile(), svnCommand);
0461:                }
0462:            }
0463:
0464:            /**
0465:             * Returns the latest file revision.
0466:             */
0467:            public String getRevisionNumber(File file) {
0468:                if (file.isDirectory()) {
0469:                    throw new IllegalArgumentException(
0470:                            "File for 'getRevisionNumber' is a directory: "
0471:                                    + file);
0472:                }
0473:
0474:                ArrayList svnCommand = new ArrayList(1);
0475:                svnCommand.add("info");
0476:                svnCommand.add(file.getName());
0477:                String info = run(file.getParentFile(), svnCommand, true);
0478:                String searchKey = "Last Changed Rev:";
0479:                int index = info.indexOf(searchKey);
0480:                if (index > 0) {
0481:                    int endIndex = info.indexOf("\n", index);
0482:                    if (endIndex > 0) {
0483:                        return info.substring(index + searchKey.length(),
0484:                                endIndex).trim();
0485:                    }
0486:                }
0487:                return null;
0488:            }
0489:
0490:            /**
0491:             * If the given module directory is not a tag, returns the latest version for that directory.
0492:             * @return null if no latest version is found
0493:             */
0494:            public ScmVersion getLatestVersion(File moduleDir) {
0495:                ScmVersion localVersion = getLocalVersion(moduleDir.getName(),
0496:                        moduleDir);
0497:                if (localVersion == null) {
0498:                    return null;
0499:                }
0500:                if (localVersion.isTag()) {
0501:                    throw new RuntimeException(
0502:                            "getLatestVersion is not possible on a Subversion tag.");
0503:                }
0504:
0505:                if (!new File(moduleDir, "module.xml").exists()) {
0506:                    throw new RuntimeException(
0507:                            "FATAL: File module.xml does not exist in the module "
0508:                                    + moduleDir.getName() + " !!!");
0509:                }
0510:
0511:                ScmVersion[] revs = getVersionsInBranch(new File(moduleDir,
0512:                        "module.xml"), localVersion);
0513:                ScmVersion latestRev = null;
0514:                if (revs.length > 0) {
0515:                    return revs[0];
0516:                } else {
0517:                    return null;
0518:                }
0519:            }
0520:
0521:            /**
0522:             * Returns the currently checked out version of the module in the given directory.
0523:             * @param moduleDir The directory where the module is currently checked out
0524:             * @return The current local version of the module
0525:             * @throws org.apache.tools.ant.BuildException
0526:             */
0527:            public ScmVersion getLocalVersion(File moduleDir)
0528:                    throws BuildException {
0529:                return getLocalVersion(moduleDir.getName(), moduleDir);
0530:            }
0531:
0532:            public ScmVersion getLocalVersion(String moduleName, File moduleDir)
0533:                    throws BuildException {
0534:                if (moduleName == null) {
0535:                    moduleName = moduleDir.getName();
0536:                }
0537:                String checkoutUrl = readCheckoutUrl(moduleDir);
0538:                if (checkoutUrl != null) {
0539:                    return parseSvnPath(moduleName, checkoutUrl);
0540:                } else {
0541:                    return null;
0542:                }
0543:            }
0544:
0545:            /**
0546:             * Reads the current Subversion checkout URL where the given module directory
0547:             * was checked out from.
0548:             */
0549:            private String readCheckoutUrl(File moduleDir) {
0550:                File svnDir = new File(moduleDir, ".svn");
0551:                if (!svnDir.exists()) {
0552:                    return null;
0553:                }
0554:
0555:                /* OLD WAY OF RETRIEVING URL, USING SLOW "svn info" COMMAND
0556:                ArrayList svnCommand = new ArrayList(1);
0557:                svnCommand.add("info");
0558:                String info = run(moduleDir, svnCommand);
0559:                int urlIndex = info.indexOf("URL:");
0560:                if (urlIndex > 0) {
0561:                	int endOfUrl = info.indexOf("\n", urlIndex);
0562:                	if (endOfUrl > 0) {
0563:                		return info.substring(urlIndex + 4, endOfUrl).trim();
0564:                	}
0565:                }
0566:                 */
0567:                try {
0568:                    String entries = FileUtils.readFileToString(new File(
0569:                            svnDir, "entries"), System
0570:                            .getProperty("file.encoding"));
0571:
0572:                    if (entries.startsWith("<?xml")) {
0573:                        // Subversion 1.3 or earler: xml format...
0574:                        int urlIndex = entries.indexOf("url=\"");
0575:                        if (urlIndex > 0) {
0576:                            entries = entries.substring(urlIndex + 5);
0577:                            int endOfUrl = entries.indexOf("\"");
0578:                            if (endOfUrl > 0) {
0579:                                return entries.substring(0, endOfUrl);
0580:                            }
0581:                        }
0582:                    } else {
0583:                        // Subversion 1.4+ : uses non-XML format...
0584:                        int urlIndex = -1;
0585:                        for (int fifthLine = 4; fifthLine-- > 0;) {
0586:                            urlIndex = entries.indexOf("\n", urlIndex + 1);
0587:                            if (urlIndex < 0) {
0588:                                return null;
0589:                            }
0590:                        }
0591:                        // we arrived at the fifth line!
0592:                        int endOfUrl = entries.indexOf("\n", urlIndex + 1);
0593:                        if (endOfUrl > 0) {
0594:                            return entries.substring(urlIndex + 1, endOfUrl)
0595:                                    .trim();
0596:                        }
0597:                    }
0598:                } catch (IOException e) {
0599:                    e.printStackTrace();
0600:                }
0601:                return null;
0602:            }
0603:
0604:            /**
0605:             * Returns all available versions for the given file in the given branch,
0606:             * with the newest number first and the oldest number last (oldest is usually the ".0" version).
0607:             */
0608:            public ScmVersion[] getVersionsInBranch(File file, ScmVersion branch) {
0609:                if (file == null) {
0610:                    throw new IllegalArgumentException(
0611:                            "File attribute for Subversion 'getVersionsInBranch' must not be null");
0612:                }
0613:                File moduleDir = file.getParentFile();
0614:                String moduleName = moduleDir.getName();
0615:
0616:                ArrayList svnCommand = new ArrayList();
0617:                svnCommand.add("list");
0618:                addAuthenticationArgs(svnCommand);
0619:
0620:                // list all tags or branches and filter the ones we want to return
0621:                String modulePath = renderUrlToSvnArg(getUrl()) + '/'
0622:                        + moduleName;
0623:                boolean returnTags = false;
0624:                if (branch == null || branch.isTrunk()) {
0625:                    // get 2 digit versions in 'branches'
0626:                    modulePath += "/branches";
0627:                } else {
0628:                    // get 3 digit versions in 'tags'
0629:                    modulePath += "/tags";
0630:                    returnTags = true;
0631:                }
0632:                svnCommand.add(modulePath);
0633:
0634:                ArrayList result = new ArrayList();
0635:
0636:                //
0637:                // get svn output and PARSE it
0638:                //
0639:                String svnResult = run(null, svnCommand);
0640:                StringTokenizer st = new StringTokenizer(svnResult, "\n");
0641:                String branchVersionString = branch
0642:                        .toString(REVISION_VERSION_SEPARATOR);
0643:                String versionString;
0644:                while (st.hasMoreTokens()) {
0645:                    versionString = st.nextToken().trim();
0646:                    if (versionString.endsWith("/")) {
0647:                        versionString = versionString.substring(0,
0648:                                versionString.length() - 1);
0649:                    }
0650:                    if (returnTags) {
0651:                        if (versionString.startsWith(branchVersionString)
0652:                                && countVersionChars(
0653:                                        REVISION_VERSION_SEPARATOR,
0654:                                        versionString) == 2) {
0655:                            result
0656:                                    .add(new ScmVersion(moduleName,
0657:                                            versionString));
0658:                        }
0659:                    } else {
0660:                        if (countVersionChars(REVISION_VERSION_SEPARATOR,
0661:                                versionString) == 1) {
0662:                            result
0663:                                    .add(new ScmVersion(moduleName,
0664:                                            versionString));
0665:                        }
0666:                    }
0667:                }
0668:
0669:                // sort and return array
0670:                Collections.sort(result);
0671:                ScmVersion[] array = new ScmVersion[result.size()];
0672:                result.toArray(array);
0673:                return array;
0674:            }
0675:
0676:            /**
0677:             * Check whether the given checkout directory is up-to-date
0678:             * when comparing it to the repository contents.
0679:             * @param checkoutDir The directory with locally checked out contents
0680:             * @return Whether the checkoutDir is up-to-date
0681:             */
0682:            public boolean isUpToDate(File checkoutDir) {
0683:                return StringUtils.isBlank(getLocalSvnChanges(checkoutDir));
0684:            }
0685:
0686:            private String getLocalSvnChanges(File checkoutDir) {
0687:                ArrayList svnCommand = new ArrayList(2);
0688:                svnCommand.add("status");
0689:                svnCommand.add("-q");
0690:                return run(checkoutDir, svnCommand);
0691:            }
0692:
0693:            /**
0694:             * Implementation of the ScmDifference interface for returning cvs diff entries in this class.
0695:             * @author Klaas Waslander
0696:             */
0697:            private static class ScmDifferenceImpl implements  ScmDifference {
0698:                String filename;
0699:                boolean conflict = false;
0700:                StringBuffer log = new StringBuffer();
0701:
0702:                ScmDifferenceImpl(String filename) {
0703:                    this .filename = filename;
0704:                }
0705:
0706:                public String getFilename() {
0707:                    return filename;
0708:                }
0709:
0710:                public boolean hasConflict() {
0711:                    return conflict;
0712:                }
0713:
0714:                private void setConflict(boolean conflict) {
0715:                    this .conflict = conflict;
0716:                }
0717:
0718:                public String getLog() {
0719:                    return log.toString();
0720:                }
0721:
0722:                private void addLogLine(String logLine) {
0723:                    this .log.append(logLine);
0724:                    this .log.append(HexDump.EOL);
0725:                }
0726:            }
0727:
0728:            /**
0729:             * Returns the files that have changed between the two given Subversion versions.
0730:             */
0731:            public ScmDifference[] getDifferences(ScmVersion version1,
0732:                    ScmVersion version2) {
0733:                if (version1.getModuleName() == null) {
0734:                    throw new IllegalArgumentException(
0735:                            "Modulename attribute (of version1) for svndiffs must not be null");
0736:                }
0737:                if (version2.getModuleName() == null) {
0738:                    throw new IllegalArgumentException(
0739:                            "Modulename attribute (of version2) for svndiffs must not be null");
0740:                }
0741:                if (!version1.getModuleName().equals(version2.getModuleName())) {
0742:                    throw new IllegalArgumentException("Module of version1 \""
0743:                            + version1.getModuleName()
0744:                            + "\" is not the same as module of version2 \""
0745:                            + version2.getModuleName() + "\"");
0746:                }
0747:
0748:                // build Subversion commandline
0749:                ArrayList svnCommand = new ArrayList();
0750:                svnCommand.add("diff");
0751:                addAuthenticationArgs(svnCommand);
0752:                svnCommand.add(renderUrlToSvnArg(getUrl()) + '/'
0753:                        + renderSvnPath(version1.getModuleName(), version1));
0754:                svnCommand.add(renderUrlToSvnArg(getUrl()) + '/'
0755:                        + renderSvnPath(version2.getModuleName(), version2));
0756:
0757:                ArrayList result = new ArrayList();
0758:
0759:                //
0760:                // get Subversion output and PARSE it
0761:                //
0762:                String svnResult = run(null, svnCommand);
0763:                try {
0764:                    BufferedReader reader = new BufferedReader(
0765:                            new StringReader(svnResult));
0766:                    String line;
0767:                    ScmDifferenceImpl currentEntry = null;
0768:
0769:                    while ((line = reader.readLine()) != null) {
0770:                        if (line.startsWith("Index:")) {
0771:                            // strip off "Index:"
0772:                            String file = line.substring(7).trim();
0773:                            // add diff entry object
0774:                            currentEntry = new ScmDifferenceImpl(file);
0775:                            result.add(currentEntry);
0776:
0777:                        } else if (currentEntry != null) {
0778:                            currentEntry.addLogLine(line);
0779:
0780:                            if (line.startsWith("! ")) {
0781:                                currentEntry.setConflict(true);
0782:                            }
0783:                        }
0784:                    }
0785:                } catch (IOException ioe) {
0786:                    ioe.printStackTrace();
0787:                }
0788:
0789:                ScmDifference[] array = new ScmDifference[result.size()];
0790:                result.toArray(array);
0791:                return array;
0792:            }
0793:
0794:            /**
0795:             * Creates a new branch in the trunk of the given module.
0796:             */
0797:            public String createBranchInTrunk(ScmVersion newBranchForModule) {
0798:                if (newBranchForModule == null) {
0799:                    throw new IllegalArgumentException(
0800:                            "newBranchForModule attribute for createBranchInTrunk must not be null");
0801:                }
0802:                ArrayList svnCommand = new ArrayList();
0803:                svnCommand.add("copy");
0804:                addAuthenticationArgs(svnCommand);
0805:
0806:                // message
0807:                svnCommand.add("-m");
0808:                svnCommand.add("Create branch " + newBranchForModule);
0809:
0810:                // from trunk
0811:                svnCommand.add(renderUrlToSvnArg(getUrl())
0812:                        + '/'
0813:                        + renderSvnPath(newBranchForModule.getModuleName(),
0814:                                null));
0815:
0816:                // to new branch
0817:                svnCommand.add(renderUrlToSvnArg(getUrl()) + '/'
0818:                        + renderSvnPath(null, newBranchForModule));
0819:
0820:                return run(null, svnCommand);
0821:            }
0822:
0823:            /**
0824:             * Creates a new tag in the given BRANCH of the given module.
0825:             */
0826:            public String createTagInBranch(ScmVersion existingBranch,
0827:                    ScmVersion newTag) {
0828:                if (existingBranch == null) {
0829:                    throw new IllegalArgumentException(
0830:                            "existingBranch attribute for createTagInBranch must not be null");
0831:                }
0832:                if (newTag == null) {
0833:                    throw new IllegalArgumentException(
0834:                            "newTag attribute for createTagInBranch must not be null");
0835:                }
0836:                if (existingBranch.getModuleName() == null) {
0837:                    throw new IllegalArgumentException(
0838:                            "moduleName of existing branch for createTagInBranch must not be null");
0839:                }
0840:
0841:                ArrayList svnCommand = new ArrayList();
0842:                svnCommand.add("copy");
0843:                addAuthenticationArgs(svnCommand);
0844:
0845:                // message
0846:                svnCommand.add("-m");
0847:                svnCommand.add("Create tag " + newTag + " in branch "
0848:                        + existingBranch);
0849:
0850:                // from branch
0851:                svnCommand.add(renderUrlToSvnArg(getUrl()) + '/'
0852:                        + renderSvnPath(null, existingBranch));
0853:
0854:                // to new tag
0855:                svnCommand.add(renderUrlToSvnArg(getUrl()) + '/'
0856:                        + renderSvnPath(null, newTag));
0857:
0858:                return run(null, svnCommand);
0859:            }
0860:
0861:            /**
0862:             * Utility method for counting the number of given characters in the given string.
0863:             */
0864:            private static int countVersionChars(char c, String s) {
0865:                // count the occurences of char c in string s
0866:                return StringUtils.countMatches(s, String.valueOf(c));
0867:            }
0868:
0869:            /**
0870:             * Runs the given svn command in the given directory, and returns standard output.
0871:             * @param baseDir The directory where the command should run
0872:             * @param commandList The command arguments (passed as arguments to the actual svn command)
0873:             * @return The standard output, if any
0874:             */
0875:            private String run(File baseDir, ArrayList commandList) {
0876:                return run(baseDir, commandList, false);
0877:            }
0878:
0879:            private String run(File baseDir, ArrayList commandList,
0880:                    boolean suppressErrorOutput) {
0881:                return run(baseDir, commandList, suppressErrorOutput, true);
0882:            }
0883:
0884:            private String run(File baseDir, ArrayList commandList,
0885:                    boolean suppressErrorOutput, boolean suppressStandardOutput) {
0886:                return run(baseDir, commandList, suppressErrorOutput,
0887:                        suppressStandardOutput, false);
0888:            }
0889:
0890:            private String run(File baseDir, ArrayList commandList,
0891:                    boolean suppressErrorOutput,
0892:                    boolean suppressStandardOutput, boolean cleaningUp) {
0893:                // work with copy for local changes
0894:                commandList = new ArrayList(commandList);
0895:                ArrayList orgCommandList = new ArrayList(commandList);
0896:
0897:                // make it quiet if not done already
0898:                String cmd = (String) commandList.get(0);
0899:                //System.err.println("SVN COMMAND: " + cmd);
0900:                if (!cmd.equals("info") && !cmd.equals("list")
0901:                        && !cmd.equals("diff") && !cmd.equals("cleanup")
0902:                        && !cmd.equals("merge") && !cmd.equals("update")
0903:                        && !cmd.equals("checkout")
0904:                        && !commandList.contains("-q")
0905:                        && !commandList.contains("--quiet")) {
0906:                    commandList.add("-q");
0907:                }
0908:
0909:                // of course, prepend the "svn" executable to invoke
0910:                commandList.add(0, AntmodProperties
0911:                        .getProperty("antmod.scm.svn.executable"));
0912:
0913:                // create launcher
0914:                ProcessLauncher launcher = new ProcessLauncher(commandList,
0915:                        baseDir);
0916:
0917:                final boolean suppressStd = suppressStandardOutput;
0918:                final StringBuffer stdOut = new StringBuffer();
0919:                final StringBuffer stdErr = new StringBuffer();
0920:                stdOut.setLength(0);
0921:                stdErr.setLength(0);
0922:                launcher
0923:                        .addOutputListener(new ProcessLauncher.OutputListener() {
0924:                            public void standardOutput(char[] output) {
0925:                                stdOut.append(output);
0926:
0927:                                if (!suppressStd) {
0928:                                    System.err.print(output);
0929:                                }
0930:                            }
0931:
0932:                            public void errorOutput(char[] output) {
0933:                                stdErr.append(output);
0934:                            }
0935:                        });
0936:
0937:                // launch and wait until done...
0938:                launcher.launch();
0939:
0940:                // detect whether to try "svn cleanup" once
0941:                if (!cleaningUp && stdErr.length() > 0
0942:                        && !cmd.equals("cleanup")
0943:                        && stdErr.indexOf("locked") > 0) {
0944:                    System.err.println("Removing lock from \""
0945:                            + baseDir.getName() + "\" using 'svn cleanup'...");
0946:                    ArrayList cleanupCommand = new ArrayList();
0947:                    cleanupCommand.add("cleanup");
0948:                    run(baseDir, cleanupCommand, false);
0949:
0950:                    // try one more time now!
0951:                    return run(baseDir, orgCommandList, suppressErrorOutput,
0952:                            suppressStandardOutput, true);
0953:                }
0954:
0955:                // if there is error output, log it for now
0956:                if (!suppressErrorOutput && stdErr.length() > 0) {
0957:                    System.err.println("'" + launcher.getCommandLine()
0958:                            + "' produced error output:");
0959:                    System.err.println(stdErr.toString());
0960:                }
0961:
0962:                // return standard output
0963:                this .standardOutput = stdOut.toString();
0964:                this .errorOutput = stdErr.toString();
0965:                return stdOut.toString();
0966:            }
0967:
0968:            static ScmVersion parseSvnPath(String moduleName, String svnPath) {
0969:                // find modulename in url
0970:                String moduleNameSearch = '/' + moduleName + '/';
0971:                int moduleNameIndex = svnPath.lastIndexOf(moduleNameSearch);
0972:                if (moduleNameIndex < 0) {
0973:                    throw new IllegalArgumentException("Subversion URL \""
0974:                            + svnPath + "\" does not contain modulename \""
0975:                            + moduleName + "\"");
0976:                }
0977:
0978:                // extract version
0979:                String versionString = svnPath.substring(moduleNameIndex
0980:                        + moduleNameSearch.length());
0981:                if (!versionString.startsWith("trunk")) {
0982:                    int nextSlash = versionString.indexOf("/");
0983:                    if (nextSlash < 0) {
0984:                        throw new IllegalArgumentException(
0985:                                "Subversion URL \""
0986:                                        + svnPath
0987:                                        + "\" does not have version in URL after tags/branches part.");
0988:                    }
0989:                    versionString = versionString.substring(nextSlash + 1);
0990:                }
0991:                return new ScmVersion(moduleName, versionString);
0992:            }
0993:
0994:            static String renderSvnPath(String moduleName, ScmVersion ver) {
0995:                if (StringUtils.isBlank(moduleName)
0996:                        && StringUtils.isBlank(ver.getModuleName())) {
0997:                    throw new RuntimeException(
0998:                            "Modulename unknown - proper Subversion repository path not possible.");
0999:                }
1000:                if (moduleName == null) {
1001:                    moduleName = ver.getModuleName();
1002:                }
1003:
1004:                if (ver == null) {
1005:                    return moduleName + "/trunk";
1006:                }
1007:
1008:                if (ver.isTag()) {
1009:                    return moduleName + "/tags/"
1010:                            + ver.toString(REVISION_VERSION_SEPARATOR);
1011:                } else if (ver.isBranch()) {
1012:                    return moduleName + "/branches/"
1013:                            + ver.toString(REVISION_VERSION_SEPARATOR);
1014:                } else {
1015:                    return moduleName + "/trunk";
1016:                }
1017:            }
1018:
1019:            static String renderUrlToSvnArg(ScmUrl url) {
1020:                StringBuffer result = new StringBuffer();
1021:                result.append(url.getProtocol());
1022:                result.append("://");
1023:                if (url.getProtocol().equals("file")) {
1024:                    result.append('/');
1025:                } else {
1026:                    result.append(url.getHost());
1027:                }
1028:                result.append(url.getPath());
1029:                return result.toString();
1030:            }
1031:
1032:            public boolean isCheckoutDir(File directory) {
1033:                return new File(directory, ".svn").exists();
1034:            }
1035:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.