Tuesday, April 17, 2012

ANT example on how to get local disk path of perforce branch

This example will show how to combine batch scripting practice with ant scripting one to make you capable to operate with the local disk paths of the branches of perforce version control system. This will also highlight the example of how to use marcrodef in ANT.

So to be able to fetch branch local path from perforce you have to know the following

  • which perforce server and port you're going to connect to
  • which credentials
  • the client you'd like to use (different clients may map the one branch to different places on your hard drive)
  • Finally the path you would like to convert

So manually the operation will look like this:
>p4 -p<server_name>:<server-port> -u<user_name> -P<password> -c<client_name> where <branch_or_file>

this command requests the server and returns the following output:
//depot/your_branch //YOUR-CLIENT/your_branch YOUR-CLIENT-ROOT\local_path_of_your_branch 
This is actually the problem preventing us from using the only ant to run it as the information we need resides at the last token of the string (YOUR-CLIENT-ROOT\local_path_of_your_branch)
That's why I use batch scripting here. The batch will take the configured command as the input, parse it and return only required part. This is achieved by a simple script (let it be named parse-p4-output.bat) that is actually represented with single line

FOR /F "tokens=3 delims= " %%A IN ('p4 -p%1:%2 -u%3 -P%4 -c%5 where %6') DO ECHO.%%A

For /F command breaks the output of the command from parentheses into set of tokens using the delimiter specified after delims= pattern. We need the third one so the command hods the following structure (taking into account that the delimiter is just the single white-space): "tokens=3 delims= "

Lets now switch to ant. To make the usage of this functionality convenient we're wrapping it with so called macrodef. Once it is defined it can be used wherever in the script in very simple way.

So, here is how it should look like. Somewhere in the ANT script we'd like to call the instruction like this:

<get-disk-path 
 path="//depot/your_branch" 
 save-to="save.to.prop"
 p4-host="your-server"
 p4-port="your-port"
 p4-user="your-user"
 p4-pswd="you-password"
 p4-clnt="YOUR-CLIENT"
/>

Here you see the obvious set of attributes. Basically the usage of such the macrodef (syntactically) does not differ from the regular ant task. The only comment for that is that after the instruction has been called the property save.to.prop will be holding the required output (and definitely you may specify your own).

Below is the definition of such the macrodef. You should describe it out of any target right under the project element.

<macrodef name="get-disk-path">
    <attribute name="p4-host"/>
    <attribute name="p4-port"/>
    <attribute name="p4-user"/>
    <attribute name="p4-pswd"/>
    <attribute name="p4-clnt"/>
    <attribute name="path"/>
    <attribute name="save-to"/>
    <sequential>
    <exec executable="parse-p4-output.bat" 
     outputproperty="@{save-to}"> 
     <arg value="@{p4-host}"/>
     <arg value="@{p4-port}"/>
     <arg value="@{p4-user}"/>
     <arg value="@{p4-pswd}"/>
     <arg value="@{p4-clnt}"/>
     <arg value="@{path}"/>
    </exec>
    </sequential>
</macrodef>

So this is how such the feature can be implemented. Inner code of macrodef calls the batch scenario. It parsed the command output and returns back to ANT. Then the output is placed into the specified property and can be used in the regular ANT instructions.