Submitted by: Les Hughes <leslie.hughes@rubus.com> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268447 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -5377,6 +5377,7 @@ current directory as <code>docs/ChangeLog.txt</code>. For example, the archive m | |||||
| <li><a href="native2ascii.html">Native2Ascii</a></li> | <li><a href="native2ascii.html">Native2Ascii</a></li> | ||||
| <li><a href="#netrexxc">NetRexxC</a></li> | <li><a href="#netrexxc">NetRexxC</a></li> | ||||
| <li><a href="propertyfile.html">PropertyFile</a></li> | <li><a href="propertyfile.html">PropertyFile</a></li> | ||||
| <li><a href="perforce.html">Perforce Tasks</a></li> | |||||
| <li><a href="#renameexts">RenameExtensions</a></li> | <li><a href="#renameexts">RenameExtensions</a></li> | ||||
| <li><a href="#script">Script</a></li> | <li><a href="#script">Script</a></li> | ||||
| <li><a href="#sound">Sound</a></li> | <li><a href="#sound">Sound</a></li> | ||||
| @@ -0,0 +1,352 @@ | |||||
| <html> | |||||
| <head> | |||||
| <title>Perforce Tasks for ANT</title> | |||||
| </head> | |||||
| <body> | |||||
| <h1>Perforce Tasks User Manual</h1> | |||||
| <p>by</p> | |||||
| <ul> | |||||
| <li>Les Hughes (<a href="mailto:leslie.hughes@rubus.com">leslie.hughes@rubus.com</a>)</li> | |||||
| </ul> | |||||
| <p>Version 1.1 - 2001/01/09</p> | |||||
| <hr> | |||||
| <h2>Contents</h2> | |||||
| <ul> | |||||
| <li><a href="#intro">Introduction</a></li> | |||||
| <li><a href="#tasks">The Tasks</a></li> | |||||
| <li><a href="#changes">Change History</a></li> | |||||
| </ul> | |||||
| <br> | |||||
| <h2><a name="intro">Introduction</a></h2> | |||||
| <p>These tasks provide an interface to the <a href="http://www.perforce.com">Perforce</a> SCM. | |||||
| The <code>org.apache.tools.ant.taskdefs.optional.perforce</code> package consists of a simple framework to support | |||||
| p4 functionality as well as some Ant tasks encapsulating frequently used (by me :-) p4 commands. | |||||
| However, the addition of new p4 commands is a pretty simple task (see the source). | |||||
| Although it is possible to use these commands on the desktop, | |||||
| they were primarily intended to be used by automated build systems.</p> | |||||
| <p><b>Note:</b> These tasks require the <a href="http://jakarta.apache.org/oro">oro 2.0</a> regular | |||||
| expression package. Simply download this package and copy the jakarta-oro-2.0.jar file into Ant's lib directory. | |||||
| You will also need the perforce client executable (p4 or p4.exe but not p4win.exe) in your path. | |||||
| </p> | |||||
| <h2><a name="tasks">The Tasks</a></h2> | |||||
| <ul> | |||||
| <table border="0" cellspacing="0" cellpadding="3"> | |||||
| <tr> | |||||
| <td><a href="#p4sync">P4Sync</a></td> | |||||
| <td>Synchronise a workspce to a depot</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td><a href="#p4change">P4Change</a></td> | |||||
| <td>Request a new changelist from the perforce server</td> | |||||
| <tr> | |||||
| <td><a href="#p4edit">P4Edit</a></td> | |||||
| <td>Open files for edit (checkout)</td> | |||||
| <tr> | |||||
| <td><a href="#p4submit">P4Submit</a></td> | |||||
| <td>Submit a changelist to the perforce server (checkin)</td> | |||||
| <tr> | |||||
| <td><a href="#p4have">P4Have</a></td> | |||||
| <td>List current files in client view, useful for reporting</td> | |||||
| <tr> | |||||
| <td><a href="#p4label">P4Label</a></td> | |||||
| <td>Create a label reflecting files in the current workspace</td> | |||||
| </tr> | |||||
| </table> | |||||
| </ul> | |||||
| <h3>General P4 Properties</h3> | |||||
| <p>Each p4 task requires a number of settings, either through build-wide properties, individual attributes | |||||
| or environment variables. These are | |||||
| </p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Property</b></td> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Env Var</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Default</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">p4.port</td> | |||||
| <td valign="top">port</td> | |||||
| <td valign="top">P4PORT</td> | |||||
| <td valign="top">The p4d server and port to connect to</td> | |||||
| <td valign="top">perforce:1666</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">p4.client</td> | |||||
| <td valign="top">client</td> | |||||
| <td valign="top">P4CLIENT</td> | |||||
| <td valign="top">The p4 client spec to use</td> | |||||
| <td valign="top">The logged in username</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">p4.user</td> | |||||
| <td valign="top">user</td> | |||||
| <td valign="top">P4USER</td> | |||||
| <td valign="top">The p4 username</td> | |||||
| <td valign="top">The logged in username</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top" align="center">--</td> | |||||
| <td valign="top">view</td> | |||||
| <td valign="top" align="center">--</td> | |||||
| <td valign="top">The client, branch or label view to operate upon. See the p4 user guide for more info.</td> | |||||
| <td valign="top">//...</td> | |||||
| </tr> | |||||
| </table> | |||||
| <p> | |||||
| Your local installation of perforce may require other settings (e.g. P4PASSWD, P4CONFIG). At the moment, these can only be set outside of Ant, as environment variables. | |||||
| </p> | |||||
| <h3>Examples</h3> | |||||
| <p>Setting in the environment:-</p> | |||||
| <p> | |||||
| (Unix csh) | |||||
| <pre>setenv P4PORT myperforcebox:1666</pre> | |||||
| (Unix sh et al) | |||||
| <pre>P4USER=myp4userid; export P4USER</pre> | |||||
| <p>Using build properties:-</p> | |||||
| <pre><property name="p4.client" value="nightlybuild"/></pre> | |||||
| <p>Using task attributes:-</p> | |||||
| <pre> | |||||
| <p4Whatever | |||||
| port="myserver:1666" | |||||
| client="smoketest" | |||||
| user="smoketestdude" | |||||
| . | |||||
| . | |||||
| . | |||||
| /> | |||||
| </pre> | |||||
| </p> | |||||
| <p> | |||||
| For more information regarding the underlying 'p4' commands you are referred to the Perforce Command Reference | |||||
| available from the <a href="http://www.perforce.com/">Perforce website</a>. | |||||
| </p> | |||||
| <h3>Taskdefs</h3> | |||||
| <p>Standard taskdefs (for you to copy'n'paste) | |||||
| <pre> | |||||
| <taskdef name="p4sync" classname="org.apache.tools.ant.taskdefs.optional.perforce.P4Sync" /> | |||||
| <taskdef name="p4change" classname="org.apache.tools.ant.taskdefs.optional.perforce.P4Change" /> | |||||
| <taskdef name="p4edit" classname="org.apache.tools.ant.taskdefs.optional.perforce.P4Edit" /> | |||||
| <taskdef name="p4submit" classname="org.apache.tools.ant.taskdefs.optional.perforce.P4Submit" /> | |||||
| <taskdef name="p4have" classname="org.apache.tools.ant.taskdefs.optional.perforce.P4Have" /> | |||||
| <taskdef name="p4label" classname="org.apache.tools.ant.taskdefs.optional.perforce.P4Label" /> | |||||
| </pre> | |||||
| <hr> | |||||
| <h2>Task Descriptions</h2> | |||||
| <h2><a name="#p4sync">P4Sync</a></h2> | |||||
| <h3>Description:</h3> | |||||
| <p>Synchronise the current workspace with the depot.</p> | |||||
| </p> | |||||
| <h3>Parameters</h3> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">force</td> | |||||
| <td valign="top">force a refresh of files</td> | |||||
| <td valign="top" align="center">no</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">label</td> | |||||
| <td valign="top">sync client to label</td> | |||||
| <td valign="top" align="center">no</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h3>Examples</h3> | |||||
| <pre><p4sync label="nightlybuild-0.0123" force="yes" /> | |||||
| <p4sync view="//depot/projects/projectfoo/main/src/..." /> | |||||
| </pre> | |||||
| <hr> | |||||
| <h2><a name="#p4change">P4Change</a></h2> | |||||
| <h3>Description:</h3> | |||||
| <p>Request a new changelist from the perforce server. | |||||
| This task sets the ${p4.change} property which can then be passed to P4Submit or P4Edit. | |||||
| </p> | |||||
| <h3>Parameters</h3> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">None</td> | |||||
| <td valign="top" align="center">--</td> | |||||
| <td valign="top" align="center">--</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h3>Examples</h3> | |||||
| <pre><p4change /> | |||||
| </pre> | |||||
| <hr> | |||||
| <h2><a name="#p4edit">P4Edit</a></h2> | |||||
| <h3>Description:</h3> | |||||
| <p>Open file(s) for edit. P4Change should be used to obtain a new changelist for P4Edit as, | |||||
| although P4Edit can open files to the default change, P4Submit cannot yet submit it. | |||||
| </p> | |||||
| <h3>Parameters</h3> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">view</td> | |||||
| <td valign="top">The filespec to request to edit</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">change</td> | |||||
| <td valign="top">An existing changelist number to assign files to.</td> | |||||
| <td valign="top" align="center">No, but see above.</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h3>Examples</h3> | |||||
| <pre> | |||||
| <p4edit | |||||
| view="//depot/projects/projectfoo/main/src/Blah.java..." | |||||
| change="${p4.change}" /> | |||||
| </pre> | |||||
| <hr> | |||||
| <h2><a name="#p4submit">P4Submit</a></h2> | |||||
| <h3>Description:</h3> | |||||
| <p>Submit a changelist, usually obtained from P4Change. | |||||
| </p> | |||||
| <h3>Parameters</h3> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">change</td> | |||||
| <td valign="top">The changelist number to submit</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h3>Examples</h3> | |||||
| <pre><p4submit change="${p4.change}" /> | |||||
| </pre> | |||||
| <hr> | |||||
| <h2><a name="#p4have">P4Have</a></h2> | |||||
| <h3>Description:</h3> | |||||
| <p>List handy file info reflecting the current client contents. | |||||
| </p> | |||||
| <h3>Parameters</h3> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">None</td> | |||||
| <td valign="top" align="center">--</td> | |||||
| <td valign="top" align="center">--</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h3>Examples</h3> | |||||
| <pre><p4have /> | |||||
| </pre> | |||||
| <hr> | |||||
| <h2><a name="#p4label">P4Label</a></h2> | |||||
| <h3>Description:</h3> | |||||
| <p>Create a new label and set contents to reflect current client file revisions. | |||||
| </p> | |||||
| <h3>Parameters</h3> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">name</td> | |||||
| <td valign="top">The name of the label</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">view</td> | |||||
| <td valign="top">client view to use for label</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">desc</td> | |||||
| <td valign="top">Label Description</td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h3>Examples</h3> | |||||
| <pre> | |||||
| <p4label | |||||
| name="NightlyBuild:${DSTAMP}:${TSTAMP}" | |||||
| desc="Auto Nightly Build" | |||||
| /> | |||||
| </pre> | |||||
| <hr> | |||||
| <h2><a name="#changes">Change History</a></h2> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top">Sept 2000</td> | |||||
| <td valign="top" align="center">--</td> | |||||
| <td valign="top">Internal Release within Rubus<td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">Nov 2000</td> | |||||
| <td valign="top">V1.0</td> | |||||
| <td valign="top">Initial Release donated to ASF :-)<td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">Jan 2001</td> | |||||
| <td valign="top">V1.1</td> | |||||
| <td valign="top">fixed cross platform (NT/Unix) bug<br>refactored p4 output handling code<br>refactored exec'ing code</td> | |||||
| </tr> | |||||
| </table> | |||||
| </body> | |||||
| </html> | |||||
| @@ -50,15 +50,21 @@ | |||||
| * individuals on behalf of the Apache Software Foundation. For more | * individuals on behalf of the Apache Software Foundation. For more | ||||
| * information on the Apache Software Foundation, please see | * information on the Apache Software Foundation, please see | ||||
| * <http://www.apache.org/>. | * <http://www.apache.org/>. | ||||
| * | |||||
| * Portions of this software are based upon public domain software | |||||
| * originally written at the National Center for Supercomputing Applications, | |||||
| * University of Illinois, Urbana-Champaign. | |||||
| */ | */ | ||||
| package org.apache.tools.ant.taskdefs.optional.perforce; | package org.apache.tools.ant.taskdefs.optional.perforce; | ||||
| import java.io.*; | import java.io.*; | ||||
| import org.apache.tools.ant.*; | import org.apache.tools.ant.*; | ||||
| //import org.apache.tools.ant.util.regexp.*; | |||||
| import org.apache.tools.ant.taskdefs.*; | |||||
| import org.apache.tools.ant.types.*; | |||||
| import org.apache.oro.text.perl.*; | import org.apache.oro.text.perl.*; | ||||
| /** Base class for Perforce (P4) ANT tasks. See individual task for example usage. | /** Base class for Perforce (P4) ANT tasks. See individual task for example usage. | ||||
| * | * | ||||
| * @see P4Sync | * @see P4Sync | ||||
| @@ -84,15 +90,15 @@ public abstract class P4Base extends org.apache.tools.ant.Task { | |||||
| protected String P4Client = ""; | protected String P4Client = ""; | ||||
| /** Perforce User (eg fbloggs) */ | /** Perforce User (eg fbloggs) */ | ||||
| protected String P4User = ""; | protected String P4User = ""; | ||||
| /** Perforce view for commands (eg //projects/foobar/main/source/... ) */ | |||||
| /** Perforce view for commands (eg //projects/foobar/main/source/... )*/ | |||||
| protected String P4View = ""; | protected String P4View = ""; | ||||
| //P4 g-opts and cmd opts (rtfm) | //P4 g-opts and cmd opts (rtfm) | ||||
| /** Perforce 'global' opts. | /** Perforce 'global' opts. | ||||
| * Forms half of low level API */ | |||||
| * Forms half of low level API */ | |||||
| protected String P4Opts = ""; | protected String P4Opts = ""; | ||||
| /** Perforce command opts. | /** Perforce command opts. | ||||
| * Forms half of low level API */ | |||||
| * Forms half of low level API */ | |||||
| protected String P4CmdOpts = ""; | protected String P4CmdOpts = ""; | ||||
| //Setters called by Ant | //Setters called by Ant | ||||
| @@ -106,73 +112,59 @@ public abstract class P4Base extends org.apache.tools.ant.Task { | |||||
| util = new Perl5Util(); | util = new Perl5Util(); | ||||
| // Not as comprehensive as Exec but Exec | |||||
| // doesn't allow stdin and stdout/stderr processing | |||||
| String myOS = System.getProperty("os.name"); | |||||
| if(myOS == null) throw new BuildException("Unable to determine OS"); | |||||
| myOS = myOS.toLowerCase(); | |||||
| if( myOS.indexOf("os/2") >= 0 ) { | |||||
| shell = "cmd /c "; | |||||
| } else if( myOS.startsWith("windows") | |||||
| && (myOS.indexOf("2000") >= 0 || myOS.indexOf("nt") >= 0 ) ) { | |||||
| shell = "cmd /c "; | |||||
| } else { | |||||
| // What about Mac OS? No perforce support there? | |||||
| shell = "/bin/sh "; //This needs testing on Unix!!!! | |||||
| } | |||||
| //Get default P4 settings from environment - Mark would have done something cool with | |||||
| //introspection here.....:-) | |||||
| String tmpprop; | |||||
| //Get default P4 settings from environment - Mark would have done something cool with | |||||
| //introspection here.....:-) | |||||
| String tmpprop; | |||||
| if((tmpprop = project.getProperty("p4.port")) != null) setPort(tmpprop); | if((tmpprop = project.getProperty("p4.port")) != null) setPort(tmpprop); | ||||
| if((tmpprop = project.getProperty("p4.client")) != null) setClient(tmpprop); | if((tmpprop = project.getProperty("p4.client")) != null) setClient(tmpprop); | ||||
| if((tmpprop = project.getProperty("p4.user")) != null) setUser(tmpprop); | |||||
| if((tmpprop = project.getProperty("p4.user")) != null) setUser(tmpprop); | |||||
| } | } | ||||
| protected void execP4Command(String command) throws BuildException { | protected void execP4Command(String command) throws BuildException { | ||||
| execP4Command(command, null, null); | |||||
| execP4Command(command, null); | |||||
| } | } | ||||
| protected void execP4Command(String command, P4OutputHandler handler) throws BuildException { | |||||
| execP4Command(command, null, handler); | |||||
| } | |||||
| /** Execute P4 command assembled by subclasses. | /** Execute P4 command assembled by subclasses. | ||||
| @param command The command to run | |||||
| @param p4input Input to be fed to command on stdin | |||||
| @param handler A P4OutputHandler to process any output | |||||
| @param command The command to run | |||||
| @param p4input Input to be fed to command on stdin | |||||
| @param handler A P4Handler to process any input and output | |||||
| */ | */ | ||||
| protected void execP4Command(String command, String p4input, P4OutputHandler handler) throws BuildException { | |||||
| protected void execP4Command(String command, P4Handler handler) throws BuildException { | |||||
| try{ | try{ | ||||
| P4Opts = P4Port+" "+P4User+" "+P4Client; | |||||
| log("Execing "+shell+"p4 "+P4Opts+" "+command, Project.MSG_VERBOSE); | |||||
| Process proc = Runtime.getRuntime().exec(shell+"p4 "+P4Opts+" "+command); | |||||
| Commandline commandline = new Commandline(); | |||||
| commandline.setExecutable("p4"); | |||||
| if(p4input != null && p4input.length() >0) { | |||||
| OutputStream out = proc.getOutputStream(); | |||||
| out.write(p4input.getBytes()); | |||||
| out.flush(); | |||||
| out.close(); | |||||
| } | |||||
| //Q: Do we need to read p4 output if we're not interested? | |||||
| BufferedReader input = new BufferedReader( | |||||
| new InputStreamReader( | |||||
| new SequenceInputStream(proc.getInputStream(),proc.getErrorStream()))); | |||||
| //Check API for these - it's how CVS does it... | |||||
| commandline.createArgument().setValue(P4Port); | |||||
| commandline.createArgument().setValue(P4User); | |||||
| commandline.createArgument().setValue(P4Client); | |||||
| commandline.createArgument().setLine(command); | |||||
| log("Execing "+commandline.getCommandline(), Project.MSG_VERBOSE); | |||||
| //we check for a match on the input to save time on the substitution. | |||||
| String line; | |||||
| while((line = input.readLine()) != null) { | |||||
| if(handler != null) handler.process(line); | |||||
| if(handler == null ) handler = new SimpleP4OutputHandler(this); | |||||
| Execute exe = new Execute(handler, null); | |||||
| exe.setAntRun(project); | |||||
| exe.setCommandline(commandline.getCommandline()); | |||||
| try{ | |||||
| exe.execute(); | |||||
| }catch(IOException e) { | |||||
| throw new BuildException(e); | |||||
| } finally { | |||||
| try{ | |||||
| handler.stop(); | |||||
| }catch(Exception e) {} | |||||
| } | } | ||||
| proc.waitFor(); | |||||
| input.close(); | |||||
| }catch(Exception e) { | |||||
| throw new BuildException("Problem exec'ing P4 command: "+e.getMessage()); | |||||
| } | |||||
| }catch(Exception e) { | |||||
| throw new BuildException("Problem exec'ing P4 command: "+e.getMessage()); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -50,6 +50,10 @@ | |||||
| * individuals on behalf of the Apache Software Foundation. For more | * individuals on behalf of the Apache Software Foundation. For more | ||||
| * information on the Apache Software Foundation, please see | * information on the Apache Software Foundation, please see | ||||
| * <http://www.apache.org/>. | * <http://www.apache.org/>. | ||||
| * | |||||
| * Portions of this software are based upon public domain software | |||||
| * originally written at the National Center for Supercomputing Applications, | |||||
| * University of Illinois, Urbana-Champaign. | |||||
| */ | */ | ||||
| package org.apache.tools.ant.taskdefs.optional.perforce; | package org.apache.tools.ant.taskdefs.optional.perforce; | ||||
| @@ -71,58 +75,63 @@ import org.apache.tools.ant.*; | |||||
| */ | */ | ||||
| public class P4Change extends P4Base { | public class P4Change extends P4Base { | ||||
| protected String emptyChangeList = null; | |||||
| protected String emptyChangeList = null; | |||||
| public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
| if(emptyChangeList == null) emptyChangeList = getEmptyChangeList(); | if(emptyChangeList == null) emptyChangeList = getEmptyChangeList(); | ||||
| final Project myProj = project; | final Project myProj = project; | ||||
| execP4Command("change -i", emptyChangeList, new P4OutputHandler() { | |||||
| public void process(String line) { | |||||
| if (util.match("/Change/", line)) { | |||||
| P4Handler handler = new P4HandlerAdapter() { | |||||
| public void process(String line) { | |||||
| if (util.match("/Change/", line)) { | |||||
| //Remove any non-numerical chars - should leave the change number | |||||
| line = util.substitute("s/[^0-9]//g", line); | |||||
| int changenumber = Integer.parseInt(line); | |||||
| log("Change Number is "+changenumber, Project.MSG_INFO); | |||||
| myProj.setProperty("p4.change", ""+changenumber); | |||||
| } else if(util.match("/error/", line)) { | |||||
| throw new BuildException("Perforce Error, check client settings and/or server"); | |||||
| } | |||||
| }}); | |||||
| //Remove any non-numerical chars - should leave the change number | |||||
| line = util.substitute("s/[^0-9]//g", line); | |||||
| int changenumber = Integer.parseInt(line); | |||||
| log("Change Number is "+changenumber, Project.MSG_INFO); | |||||
| myProj.setProperty("p4.change", ""+changenumber); | |||||
| } else if(util.match("/error/", line)) { | |||||
| throw new BuildException("Perforce Error, check client settings and/or server"); | |||||
| } | |||||
| }}; | |||||
| handler.setOutput(emptyChangeList); | |||||
| execP4Command("change -i", handler); | |||||
| } | } | ||||
| public String getEmptyChangeList() throws BuildException { | public String getEmptyChangeList() throws BuildException { | ||||
| final StringBuffer stringbuf = new StringBuffer(); | final StringBuffer stringbuf = new StringBuffer(); | ||||
| execP4Command("change -o", new P4OutputHandler() { | |||||
| public void process(String line) { | |||||
| if(!util.match("/^#/",line)){ | |||||
| if(util.match("/error/", line)) { | |||||
| log("Client Error", Project.MSG_VERBOSE); | |||||
| throw new BuildException("Perforce Error, check client settings and/or server"); | |||||
| } else if(util.match("/<enter description here>/",line)) { | |||||
| line = util.substitute("s/<enter description here>/AutoSubmit By Ant/", line); | |||||
| } else if(util.match("/\\/\\//", line)) { | |||||
| //Match "//" for begining of depot filespec | |||||
| return; | |||||
| } | |||||
| stringbuf.append(line); | |||||
| stringbuf.append("\n"); | |||||
| } | |||||
| }}); | |||||
| return stringbuf.toString(); | |||||
| execP4Command("change -o", new P4HandlerAdapter() { | |||||
| public void process(String line) { | |||||
| if(!util.match("/^#/",line)){ | |||||
| if(util.match("/error/", line)) { | |||||
| log("Client Error", Project.MSG_VERBOSE); | |||||
| throw new BuildException("Perforce Error, check client settings and/or server"); | |||||
| } else if(util.match("/<enter description here>/",line)) { | |||||
| line = util.substitute("s/<enter description here>/AutoSubmit By Ant/", line); | |||||
| } else if(util.match("/\\/\\//", line)) { | |||||
| //Match "//" for begining of depot filespec | |||||
| return; | |||||
| } | |||||
| stringbuf.append(line); | |||||
| stringbuf.append("\n"); | |||||
| } | |||||
| }}); | |||||
| return stringbuf.toString(); | |||||
| } | } | ||||
| @@ -50,6 +50,10 @@ | |||||
| * individuals on behalf of the Apache Software Foundation. For more | * individuals on behalf of the Apache Software Foundation. For more | ||||
| * information on the Apache Software Foundation, please see | * information on the Apache Software Foundation, please see | ||||
| * <http://www.apache.org/>. | * <http://www.apache.org/>. | ||||
| * | |||||
| * Portions of this software are based upon public domain software | |||||
| * originally written at the National Center for Supercomputing Applications, | |||||
| * University of Illinois, Urbana-Champaign. | |||||
| */ | */ | ||||
| package org.apache.tools.ant.taskdefs.optional.perforce; | package org.apache.tools.ant.taskdefs.optional.perforce; | ||||
| @@ -65,17 +69,17 @@ import org.apache.tools.ant.*; | |||||
| * ToDo: Should call reopen if file is already open in one of our changelists perhaps? | * ToDo: Should call reopen if file is already open in one of our changelists perhaps? | ||||
| */ | */ | ||||
| public class P4Edit extends P4Base { | |||||
| public class P4Edit extends P4Base { | |||||
| public String change = null; | |||||
| public String change = null; | |||||
| public void setChange(String change) { | |||||
| this.change = change; | |||||
| } | |||||
| public void execute() throws BuildException { | |||||
| if(change != null ) P4CmdOpts = "-c "+change; | |||||
| if(P4View == null) throw new BuildException("No view specified to edit"); | |||||
| execP4Command("-s edit "+P4CmdOpts+" "+P4View, new SimpleP4OutputHandler(this)); | |||||
| } | |||||
| public void setChange(String change) { | |||||
| this.change = change; | |||||
| } | |||||
| public void execute() throws BuildException { | |||||
| if(change != null ) P4CmdOpts = "-c "+change; | |||||
| if(P4View == null) throw new BuildException("No view specified to edit"); | |||||
| execP4Command("-s edit "+P4CmdOpts+" "+P4View, new SimpleP4OutputHandler(this)); | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,69 @@ | |||||
| /* | |||||
| * The Apache Software License, Version 1.1 | |||||
| * | |||||
| * Copyright (c) 1999, 2000 The Apache Software Foundation. All rights | |||||
| * reserved. | |||||
| * | |||||
| * Redistribution and use in source and binary forms, with or without | |||||
| * modification, are permitted provided that the following conditions | |||||
| * are met: | |||||
| * | |||||
| * 1. Redistributions of source code must retain the above copyright | |||||
| * notice, this list of conditions and the following disclaimer. | |||||
| * | |||||
| * 2. Redistributions in binary form must reproduce the above copyright | |||||
| * notice, this list of conditions and the following disclaimer in | |||||
| * the documentation and/or other materials provided with the | |||||
| * distribution. | |||||
| * | |||||
| * 3. The end-user documentation included with the redistribution, if | |||||
| * any, must include the following acknowlegement: | |||||
| * "This product includes software developed by the | |||||
| * Apache Software Foundation (http://www.apache.org/)." | |||||
| * Alternately, this acknowlegement may appear in the software itself, | |||||
| * if and wherever such third-party acknowlegements normally appear. | |||||
| * | |||||
| * 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||||
| * Foundation" must not be used to endorse or promote products derived | |||||
| * from this software without prior written permission. For written | |||||
| * permission, please contact apache@apache.org. | |||||
| * | |||||
| * 5. Products derived from this software may not be called "Apache" | |||||
| * nor may "Apache" appear in their names without prior written | |||||
| * permission of the Apache Group. | |||||
| * | |||||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
| * SUCH DAMAGE. | |||||
| * ==================================================================== | |||||
| * | |||||
| * This software consists of voluntary contributions made by many | |||||
| * individuals on behalf of the Apache Software Foundation. For more | |||||
| * information on the Apache Software Foundation, please see | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| package org.apache.tools.ant.taskdefs.optional.perforce; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; | |||||
| /** Interface for p4 job output stream handler. Classes implementing this interface | |||||
| * can be called back by P4Base.execP4Command(); | |||||
| * | |||||
| * @author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
| */ | |||||
| public interface P4Handler extends ExecuteStreamHandler { | |||||
| public void process(String line) throws BuildException; | |||||
| public void setOutput(String line) throws BuildException; | |||||
| } | |||||
| @@ -0,0 +1,119 @@ | |||||
| /* | |||||
| * The Apache Software License, Version 1.1 | |||||
| * | |||||
| * Copyright (c) 1999, 2000 The Apache Software Foundation. All rights | |||||
| * reserved. | |||||
| * | |||||
| * Redistribution and use in source and binary forms, with or without | |||||
| * modification, are permitted provided that the following conditions | |||||
| * are met: | |||||
| * | |||||
| * 1. Redistributions of source code must retain the above copyright | |||||
| * notice, this list of conditions and the following disclaimer. | |||||
| * | |||||
| * 2. Redistributions in binary form must reproduce the above copyright | |||||
| * notice, this list of conditions and the following disclaimer in | |||||
| * the documentation and/or other materials provided with the | |||||
| * distribution. | |||||
| * | |||||
| * 3. The end-user documentation included with the redistribution, if | |||||
| * any, must include the following acknowlegement: | |||||
| * "This product includes software developed by the | |||||
| * Apache Software Foundation (http://www.apache.org/)." | |||||
| * Alternately, this acknowlegement may appear in the software itself, | |||||
| * if and wherever such third-party acknowlegements normally appear. | |||||
| * | |||||
| * 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||||
| * Foundation" must not be used to endorse or promote products derived | |||||
| * from this software without prior written permission. For written | |||||
| * permission, please contact apache@apache.org. | |||||
| * | |||||
| * 5. Products derived from this software may not be called "Apache" | |||||
| * nor may "Apache" appear in their names without prior written | |||||
| * permission of the Apache Group. | |||||
| * | |||||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
| * SUCH DAMAGE. | |||||
| * ==================================================================== | |||||
| * | |||||
| * This software consists of voluntary contributions made by many | |||||
| * individuals on behalf of the Apache Software Foundation. For more | |||||
| * information on the Apache Software Foundation, please see | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| package org.apache.tools.ant.taskdefs.optional.perforce; | |||||
| import java.io.*; | |||||
| import org.apache.tools.ant.*; | |||||
| public abstract class P4HandlerAdapter implements P4Handler { | |||||
| public abstract void process(String line); | |||||
| String p4input = ""; | |||||
| //set any data to be written to P4's stdin - messy, needs work | |||||
| public void setOutput(String p4Input) { | |||||
| this.p4input = p4Input; | |||||
| } | |||||
| public void start() throws BuildException { | |||||
| try{ | |||||
| //First write any output to P4 | |||||
| if(p4input != null && p4input.length() >0 && os != null) { | |||||
| os.write(p4input.getBytes()); | |||||
| os.flush(); | |||||
| os.close(); | |||||
| } | |||||
| //Now read any input and process | |||||
| BufferedReader input = new BufferedReader( | |||||
| new InputStreamReader( | |||||
| new SequenceInputStream(is,es))); | |||||
| String line; | |||||
| while((line = input.readLine()) != null) { | |||||
| process(line); | |||||
| } | |||||
| input.close(); | |||||
| }catch(Exception e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| OutputStream os; //OUtput | |||||
| InputStream is; //Input | |||||
| InputStream es; //Error | |||||
| public void setProcessInputStream(OutputStream os) throws IOException { | |||||
| this.os = os; | |||||
| } | |||||
| public void setProcessErrorStream(InputStream is) throws IOException { | |||||
| this.es = is; | |||||
| } | |||||
| public void setProcessOutputStream(InputStream is) throws IOException { | |||||
| this.is = is; | |||||
| } | |||||
| public void stop(){} | |||||
| } | |||||
| @@ -50,6 +50,10 @@ | |||||
| * individuals on behalf of the Apache Software Foundation. For more | * individuals on behalf of the Apache Software Foundation. For more | ||||
| * information on the Apache Software Foundation, please see | * information on the Apache Software Foundation, please see | ||||
| * <http://www.apache.org/>. | * <http://www.apache.org/>. | ||||
| * | |||||
| * Portions of this software are based upon public domain software | |||||
| * originally written at the National Center for Supercomputing Applications, | |||||
| * University of Illinois, Urbana-Champaign. | |||||
| */ | */ | ||||
| package org.apache.tools.ant.taskdefs.optional.perforce; | package org.apache.tools.ant.taskdefs.optional.perforce; | ||||
| @@ -50,6 +50,10 @@ | |||||
| * individuals on behalf of the Apache Software Foundation. For more | * individuals on behalf of the Apache Software Foundation. For more | ||||
| * information on the Apache Software Foundation, please see | * information on the Apache Software Foundation, please see | ||||
| * <http://www.apache.org/>. | * <http://www.apache.org/>. | ||||
| * | |||||
| * Portions of this software are based upon public domain software | |||||
| * originally written at the National Center for Supercomputing Applications, | |||||
| * University of Illinois, Urbana-Champaign. | |||||
| */ | */ | ||||
| package org.apache.tools.ant.taskdefs.optional.perforce; | package org.apache.tools.ant.taskdefs.optional.perforce; | ||||
| @@ -112,17 +116,21 @@ public class P4Label extends P4Base { | |||||
| "Options: unlocked\n"+ | "Options: unlocked\n"+ | ||||
| "View: "+P4View+"\n"; | "View: "+P4View+"\n"; | ||||
| execP4Command("label -i", newLabel, new P4OutputHandler() { | |||||
| public void process(String line) { | |||||
| log(line, Project.MSG_VERBOSE); | |||||
| } | |||||
| }); | |||||
| P4Handler handler = new P4HandlerAdapter() { | |||||
| public void process(String line) { | |||||
| log(line, Project.MSG_VERBOSE); | |||||
| } | |||||
| }; | |||||
| handler.setOutput(newLabel); | |||||
| execP4Command("label -i", handler); | |||||
| execP4Command("labelsync -l "+name, null, new P4OutputHandler() { | |||||
| public void process(String line) { | |||||
| log(line, Project.MSG_VERBOSE); | |||||
| } | |||||
| }); | |||||
| execP4Command("labelsync -l "+name, new P4HandlerAdapter() { | |||||
| public void process(String line) { | |||||
| log(line, Project.MSG_VERBOSE); | |||||
| } | |||||
| }); | |||||
| log("Created Label "+name+" ("+desc+")", Project.MSG_INFO); | log("Created Label "+name+" ("+desc+")", Project.MSG_INFO); | ||||
| @@ -50,6 +50,10 @@ | |||||
| * individuals on behalf of the Apache Software Foundation. For more | * individuals on behalf of the Apache Software Foundation. For more | ||||
| * information on the Apache Software Foundation, please see | * information on the Apache Software Foundation, please see | ||||
| * <http://www.apache.org/>. | * <http://www.apache.org/>. | ||||
| * | |||||
| * Portions of this software are based upon public domain software | |||||
| * originally written at the National Center for Supercomputing Applications, | |||||
| * University of Illinois, Urbana-Champaign. | |||||
| */ | */ | ||||
| package org.apache.tools.ant.taskdefs.optional.perforce; | package org.apache.tools.ant.taskdefs.optional.perforce; | ||||
| @@ -75,20 +79,20 @@ public class P4Submit extends P4Base { | |||||
| public void setChange(String change) { | public void setChange(String change) { | ||||
| this.change = change; | this.change = change; | ||||
| } | |||||
| } | |||||
| public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
| if(change != null) { | if(change != null) { | ||||
| execP4Command("submit -c "+change, new P4OutputHandler(){ | |||||
| public void process(String line) { | |||||
| log(line, Project.MSG_VERBOSE); | |||||
| } | |||||
| }); | |||||
| } else { | |||||
| //here we'd parse the output from change -o into submit -i | |||||
| //in order to support default change. | |||||
| throw new BuildException("No change specified (no support for default change yet...."); | |||||
| } | |||||
| } | |||||
| execP4Command("submit -c "+change, new P4HandlerAdapter(){ | |||||
| public void process(String line) { | |||||
| log(line, Project.MSG_VERBOSE); | |||||
| } | |||||
| }); | |||||
| } else { | |||||
| //here we'd parse the output from change -o into submit -i | |||||
| //in order to support default change. | |||||
| throw new BuildException("No change specified (no support for default change yet...."); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -50,6 +50,10 @@ | |||||
| * individuals on behalf of the Apache Software Foundation. For more | * individuals on behalf of the Apache Software Foundation. For more | ||||
| * information on the Apache Software Foundation, please see | * information on the Apache Software Foundation, please see | ||||
| * <http://www.apache.org/>. | * <http://www.apache.org/>. | ||||
| * | |||||
| * Portions of this software are based upon public domain software | |||||
| * originally written at the National Center for Supercomputing Applications, | |||||
| * University of Illinois, Urbana-Champaign. | |||||
| */ | */ | ||||
| package org.apache.tools.ant.taskdefs.optional.perforce; | package org.apache.tools.ant.taskdefs.optional.perforce; | ||||
| @@ -80,7 +84,7 @@ public class P4Sync extends P4Base { | |||||
| public void setLabel(String label) throws BuildException { | public void setLabel(String label) throws BuildException { | ||||
| if(label == null && !label.equals("")) | if(label == null && !label.equals("")) | ||||
| throw new BuildException("P4Sync: Labels cannot be Null or Empty"); | |||||
| throw new BuildException("P4Sync: Labels cannot be Null or Empty"); | |||||
| this.label = label; | this.label = label; | ||||
| @@ -89,20 +93,20 @@ public class P4Sync extends P4Base { | |||||
| public void setForce(String force) throws BuildException { | public void setForce(String force) throws BuildException { | ||||
| if(force == null && !label.equals("")) | if(force == null && !label.equals("")) | ||||
| throw new BuildException("P4Sync: If you want to force, set force to non-null string!"); | |||||
| P4CmdOpts = "-f"; | |||||
| } | |||||
| throw new BuildException("P4Sync: If you want to force, set force to non-null string!"); | |||||
| P4CmdOpts = "-f"; | |||||
| } | |||||
| public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
| if (P4View != null) { | if (P4View != null) { | ||||
| syncCmd = P4View; | |||||
| syncCmd = P4View; | |||||
| } | } | ||||
| if(label != null && !label.equals("")) { | if(label != null && !label.equals("")) { | ||||
| syncCmd = syncCmd + "@" + label; | |||||
| syncCmd = syncCmd + "@" + label; | |||||
| } | } | ||||
| @@ -50,38 +50,42 @@ | |||||
| * individuals on behalf of the Apache Software Foundation. For more | * individuals on behalf of the Apache Software Foundation. For more | ||||
| * information on the Apache Software Foundation, please see | * information on the Apache Software Foundation, please see | ||||
| * <http://www.apache.org/>. | * <http://www.apache.org/>. | ||||
| * | |||||
| * Portions of this software are based upon public domain software | |||||
| * originally written at the National Center for Supercomputing Applications, | |||||
| * University of Illinois, Urbana-Champaign. | |||||
| */ | */ | ||||
| package org.apache.tools.ant.taskdefs.optional.perforce; | package org.apache.tools.ant.taskdefs.optional.perforce; | ||||
| import org.apache.tools.ant.*; | import org.apache.tools.ant.*; | ||||
| public class SimpleP4OutputHandler implements P4OutputHandler { | |||||
| public class SimpleP4OutputHandler extends P4HandlerAdapter { | |||||
| P4Base parent; | |||||
| public SimpleP4OutputHandler(P4Base parent) { | |||||
| this.parent = parent; | |||||
| } | |||||
| public void process(String line) throws BuildException { | |||||
| if(parent.util.match("/^exit/",line)) return; | |||||
| P4Base parent; | |||||
| public SimpleP4OutputHandler(P4Base parent) { | |||||
| this.parent = parent; | |||||
| } | |||||
| public void process(String line) throws BuildException { | |||||
| if(parent.util.match("/^exit/",line)) return; | |||||
| //Throw exception on errors (except up-to-date) | |||||
| //p4 -s is unpredicatable. For example a server down | |||||
| //does not return error: markup | |||||
| // | |||||
| //Some forms producing commands (p4 -s change -o) do tag the output | |||||
| //others don't..... | |||||
| //Others mark errors as info, for example edit a file | |||||
| //which is already open for edit..... | |||||
| //Just look for error: - catches most things.... | |||||
| //Throw exception on errors (except up-to-date) | |||||
| //p4 -s is unpredicatable. For example a server down | |||||
| //does not return error: markup | |||||
| // | |||||
| //Some forms producing commands (p4 -s change -o) do tag the output | |||||
| //others don't..... | |||||
| //Others mark errors as info, for example edit a file | |||||
| //which is already open for edit..... | |||||
| //Just look for error: - catches most things.... | |||||
| if(parent.util.match("/error:/", line) && !parent.util.match("/up-to-date/", line)) { | |||||
| throw new BuildException(line); | |||||
| } | |||||
| if(parent.util.match("/error:/", line) && !parent.util.match("/up-to-date/", line)) { | |||||
| throw new BuildException(line); | |||||
| } | |||||
| parent.log(parent.util.substitute("s/^.*: //",line), Project.MSG_INFO); | |||||
| } | |||||
| parent.log(parent.util.substitute("s/^.*: //",line), Project.MSG_INFO); | |||||
| } | |||||
| } | } | ||||