Skip to content
February 23, 2011 / edeustace

Dealing with p4 login in continuous builds

On my current project we added a target to our ant build to tag the build with the perforce revision.

This worked fine on our local machines but not on Hudson as we weren’t able to login.
I was looking at solutions and saw this:
However I wanted to return the ticket back to the console for further use within my Ant target.

To get around this we need to:
1. Login using “p4 login” every time
2. Invoke any subsequent p4 requests passing in the ticket that perforce returns

However p4 login is an interactive command – no good for build systems. To get around this I’ve created a runnable jar that invokes p4 login, enters the password at the prompt then outputs the ticket for use with subsequent requests.

So now we can call:

P4 –u user –P ${} changes //MyDepot/MyProject/...


 <target name="write-version-info">
	<exec dir="${basedir}"
            <arg line="/c java -jar P4Login.jar ${p4.user} ${p4.password}"/>
	<exec dir="${basedir}"
            <arg line="/c p4 -P ${p4.login.ticket} -u ${p4.user} changes -s submitted -m1 ${p4.project.root}"/>
        <propertyregex property="last.commit.number"
            regexp="Change (.*?) on"
          <echo>We now have the latest revision: ${last.commit.number}</echo>

The java code takes 2 arguments: username and passsword (it expects the remaining P4 variables to be set in your environment. It then interacts with the interactive login command:

import java.text.MessageFormat;

public class P4LoginMain {

	public static void main(String[] args) throws Exception {

		String p4Ticket = null;
		if (args.length != 2) {
			throw new RuntimeException("you must supply username and password");

		String username = args[0];
		String password = args[1];

		StringBuilder sb = new StringBuilder();
		String loginCmd = MessageFormat.format("p4 -u {0} login -p", username);

		Runtime runtime = Runtime.getRuntime();
		Process p = runtime.exec(loginCmd);
		OutputStream os = p.getOutputStream();

		InputStream lsOut = p.getInputStream();
		InputStreamReader r = new InputStreamReader(lsOut);
		BufferedReader in = new BufferedReader(r);

		String line;
		while ((line = in.readLine()) != null) {
			if (line.indexOf("Enter password:") == -1) {
				p4Ticket = line.trim();
		int returncode = p.waitFor();

		if (returncode != 0 || p4Ticket == null) {
			throw new Exception("Problem in login. Return code: " + returncode + " Output:" + sb);

To use – compile the java source into a Runnable jar the call it: java -jar P4Login.jar ed password


One Comment

Leave a Comment
  1. Mauro Ribeiro / Jul 1 2013 12:52 pm

    Another straightforward way to do it is one of the following:

    A) echo passwd| p4 -u username login

    Note that there is no space between the password and the pipe

    B) Login into one p4 client machine, use p4 set. You will see a environment variable called P4PASSWD with a hash value. This hash is the MD5 version of your password, so you can set the same hash value in the build server machine, which in turn will supress the need to store your password in plain text as in A) above.

    (in a client machine)
    p4 set

    (in the build machine or inside the build script)
    export P4PASSWD=EF2AB1E5DBC3C88477E23BFE12A06D6B

    Hope it helps.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: