DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG· RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT <http://issues.apache.org/bugzilla/show_bug.cgi?id=42462>. ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND· INSERTED IN THE BUG DATABASE.
http://issues.apache.org/bugzilla/show_bug.cgi?id=42462 Summary: Cuntributing optional task for ClearCase findmerge Product: Ant Version: unspecified Platform: All OS/Version: All Status: NEW Keywords: PatchAvailable Severity: enhancement Priority: P2 Component: Optional SCM tasks AssignedTo: dev@ant.apache.org ReportedBy: [EMAIL PROTECTED] The ClearCase optional tasks (http://ant.apache.org/manual/OptionalTasks/clearcase.html) don't offer support for merge operations. I have written a 'CCFindmerge' task that inherits from org.apache.tools.ant.taskdefs.optional.clearcase.ClearCase, pretty much in the same vain as the other cc tasks. Performing a 'findmerge' from your Ant build file is quite useful in situations where a view/branch needs to be up-to-date with another view/branch ( e.g. the mainline) before the build can proceed. If a merge is necessary, this command will fail the build (i.e. throw a BuildException). I thought that maybe other Ant/ClearCase users out there could use this task too, so I would like to contribute CCFindmerge to the Apache Ant codebase. I have done a svn diff. Please find the patch below. Regards and many thanks for your continuing support of Ant. Index: /ant-trunk/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCFindmerge.java =================================================================== --- /ant-trunk/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCFindmerge.java (revision 0) +++ /ant-trunk/src/main/org/apache/tools/ant/taskdefs/optional/clearcase/CCFindmerge.java (revision 0) @@ -0,0 +1,384 @@ +/* + * Copyright 2000-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.tools.ant.taskdefs.optional.clearcase; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.Commandline; + +/** + * Performs a ClearCase findmerge. + * + * The command will not actually merge anything, just fail the build if a merge is necessary. This check is quite useful + * in situations where a view/branch needs to be up-to-date with another view/branch (e.g. main) before running build + * can be run. + * + * <p> + * The following attributes are interpreted: + * + * <table border="1"> + * <tr> + * <th>Attribute</th> + * <th>Values</th> + * <th>Required</th> + * </tr> + * <tr> + * <td>viewpath</td> + * <td>Path to the ClearCase view file or directory that the command will operate on</td> + * <td>No</td> + * </tr> + * <tr> + * <td>viewtag</td> + * <td>view-tag. Compare the version selected by your view with the version selected by the view specified by view-tag. + * view-tag may not specify a snapshot view. A version of the same element is always used, even if the version has a + * different name in the other view.</td> + * <td>No</td> + * </tr> + * <tr> + * <td>version</td> + * <td>version-selector. Compare with the version specified by the version-selector. A version selector involving a + * branch type, for example /main/LATEST or .../branch1/LATEST, is optimized for selecting the set of versions to + * consider and performs better than other types of queries. If the branch exists only on a relatively small number of + * versions in the VOB, this option performs much better than other types of queries.</td> + * <td>No</td> + * </tr> + * <tr> + * <td>latest</td> + * <td>(Consider only versions that are currently checked out.) Compare with the most recent version on the branch from + * which your version was checked out. This option is useful with versions for which you have unreserved checkouts: if + * one or more new versions have been checked in by other users, you must merge the most recent one into your + * checked-out version before you can perform a checkin.</td> + * <td>No</td> + * </tr> + * <tr> + * <td>depth</td> + * <td>Causes directory entries to be processed before the directory itself.</td> + * <td>No</td> + * </tr> + * <tr> + * <td>nrecurse</td> + * <td>For each directory version, considers the file and directory versions within it, but does not descend into its + * subdirectories.</td> + * <td>No</td> + * </tr> + * <tr> + * <td>directory</td> + * <td>For each directory, considers only the directory itself, not the directory or file versions, or VOB symbolic + * links it catalogs.</td> + * <td>No</td> + * </tr> + * <tr> + * <td>follow</td> + * <td>Causes VOB symbolic links to be traversed.</td> + * <td>No</td> + * </tr> + * <tr> + * <td>nzero</td> + * <td>Does not perform a merge if the from-contributor is version 0 on its branch. This gives you the opportunity to + * delete the empty branch, and then perform a merge from the version at which the branch was created.</td> + * <td>No</td> + * </tr> + * <tr> + * <td>nback</td> + * <td>Does not perform the merge in the case described earlier. It may be appropriate to simulate the merge by moving + * the version label down to the from-version. Note, however, that this alternative leaves the version without a + * subbranch, which may or may not be desirable.</td> + * <td>No</td> + * </tr> + * <tr> + * <td>whynot</td> + * <td>For each version that does not require a merge, displays a message explaining the reason. This is especially + * useful when you are merging between views whose namespaces differ significantly.</td> + * <td>No</td> + * </tr> + * <tr> + * <td>visible</td> + * <td>Suppresses the warning messages for versions that are not visible in the current view.</td> + * <td>No</td> + * </tr> + * <tr> + * <tr> + * <td>log</td> + * <td>pname. Creates pname as the merge log file, instead of selecting a name automatically. To suppress creation of a + * merge log file, use log /dev/null (UNIX) or log NUL (Windows)</td> + * <td>No</td> + * </tr> + * <tr> + * <td>failonerr</td> + * <td>Throw an exception if the command fails. Default is true.</td> + * <td>No</td> + * </tr> + * </table> + * + * @author Fabio Gavilondo + */ +public class CCFindmerge extends ClearCase { + public static final String COMMAND_FINDMERGE = "findmerge"; + + private static final String FLAG_VIEWTAG = "-ftag"; + + private static final String FLAG_VERSION = "-fversion"; + + private static final String FLAG_LATEST = "-flatest"; + + private static final String FLAG_DEPTH = "-depth"; + + private static final String FLAG_NRECURSE = "-nrecurse"; + + private static final String FLAG_DIRECTORY = "-directory"; + + private static final String FLAG_FOLLOW = "-follow"; + + private static final String FLAG_VISIBLE = "-visible"; + + private static final String FLAG_NZERO = "-nzero"; + + private static final String FLAG_NBACK = "-nback"; + + private static final String FLAG_WHYNOT = "-whynot"; + + private static final String FLAG_LOG = "-log"; + + private static final String FLAG_PRINT = "-print"; + + private String viewtag = null; + + private String version = null; + + private boolean latest = false; + + private boolean depth = false; + + private boolean nrecurse = false; + + private boolean directory = false; + + private boolean follow = false; + + private boolean visible = false; + + private boolean nzero = false; + + private boolean nback = false; + + private boolean whynot = false; + + private String log = null; + + public boolean getDepth() { + return depth; + } + + public void setDepth(boolean depth) { + this.depth = depth; + } + + public boolean getDirectory() { + return directory; + } + + public void setDirectory(boolean directory) { + this.directory = directory; + } + + public boolean getFollow() { + return follow; + } + + public void setFollow(boolean follow) { + this.follow = follow; + } + + public boolean getLatest() { + return latest; + } + + public void setLatest(boolean latest) { + this.latest = latest; + } + + public String getLog() { + return log; + } + + public void setLog(String log) { + this.log = log; + } + + public boolean getNback() { + return nback; + } + + public void setNback(boolean nback) { + this.nback = nback; + } + + public boolean getNrecurse() { + return nrecurse; + } + + public void setNrecurse(boolean nrecurse) { + this.nrecurse = nrecurse; + } + + public boolean getNzero() { + return nzero; + } + + public void setNzero(boolean nzero) { + this.nzero = nzero; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getViewtag() { + return viewtag; + } + + public void setViewtag(String viewtag) { + this.viewtag = viewtag; + } + + public boolean getVisible() { + return visible; + } + + public void setVisible(boolean visible) { + this.visible = visible; + } + + public boolean getWhynot() { + return whynot; + } + + public void setWhynot(boolean whynot) { + this.whynot = whynot; + } + + public void execute() throws BuildException { + Commandline commandLine = new Commandline(); + Project aProj = getProject(); + + // Default the viewpath to basedir if it is not specified + if (getViewPath() == null) { + setViewPath(aProj.getBaseDir().getPath()); + } + + commandLine.setExecutable(getClearToolCommand()); + commandLine.createArgument().setValue(COMMAND_FINDMERGE); + + // Check the command line options + checkOptions(commandLine); + + // For debugging + getProject().log(commandLine.toString(), Project.MSG_DEBUG); + + if (!getFailOnErr()) { + getProject().log("Ignoring any errors that occur for: " + getViewPathBasename(), Project.MSG_VERBOSE); + } + + getProject().log("running command line: " + commandLine.toString(), Project.MSG_VERBOSE); + String result = runS(commandLine); + getProject().log("findmerge result: " + result, Project.MSG_VERBOSE); + + if (getFailOnErr() && isCleartoolErrorOutput(result)) { + String msg = "Failed executing: \"" + commandLine.toString() + "\". Reason: " + result; + throw new BuildException(msg, getLocation()); + } + + if (result.contains("Needs Merge")) { + String msg = "Path: " + getViewPath() + " needs merge from " + getMergeSourceDescription(); + throw new BuildException(msg, getLocation()); + } + } + + private boolean isCleartoolErrorOutput(String output) { + return output.contains("cleartool: Error:"); + } + + private String getMergeSourceDescription() { + if (getViewtag() != null) { + return "view " + getViewtag(); + } else if (getVersion() != null) { + return "version " + getVersion(); + } else { + return "latest from branch"; + } + } + + /** + * Check the command line options. + */ + private void checkOptions(Commandline cmd) { + cmd.createArgument().setValue(getViewPath()); + + if (getViewtag() != null) { + createArgumentWithValue(cmd, FLAG_VIEWTAG, getViewtag()); + } else if (getVersion() != null) { + createArgumentWithValue(cmd, FLAG_VERSION, getVersion()); + } else if (getLatest()) { + cmd.createArgument().setValue(FLAG_LATEST); + } + + if (getDepth()) { + cmd.createArgument().setValue(FLAG_DEPTH); + } + if (getNrecurse()) { + cmd.createArgument().setValue(FLAG_NRECURSE); + } + if (getDirectory()) { + cmd.createArgument().setValue(FLAG_DIRECTORY); + } + if (getFollow()) { + cmd.createArgument().setValue(FLAG_FOLLOW); + } + if (getVisible()) { + cmd.createArgument().setValue(FLAG_VISIBLE); + } + if (getNzero()) { + cmd.createArgument().setValue(FLAG_NZERO); + } + if (getNback()) { + cmd.createArgument().setValue(FLAG_NBACK); + } + if (getWhynot()) { + cmd.createArgument().setValue(FLAG_WHYNOT); + } + + if (getLog() != null) { + createArgumentWithValue(cmd, FLAG_LOG, getLog()); + } + + cmd.createArgument().setValue(FLAG_PRINT); + } + + private static void createArgumentWithValue(Commandline cmd, String argument, String value) { + /* + * Had to make two separate commands here because if a space is inserted between the flag and the value, it is + * treated as a Windows filename with a space and it is enclosed in double quotes ("). This breaks clearcase. + */ + cmd.createArgument().setValue(argument); + cmd.createArgument().setValue(value); + } +} -- Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the assignee for the bug, or are watching the assignee. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]