Perforce Extension for PHP

User Documentation

Author: Jon Parise
Contact: jon@php.net
Data:2008/03/13
Revision: #13

Contents

1   Overview

Perforce is a fast, professional Software Configuration Management system. The Perforce Extension for PHP wraps the public Perforce C/++ API, giving PHP developers direct access to Perforce's native client functions.

1.1   Requirements

The Perforce extension has the following system requirements:

  • PHP version 5.2.0 or later
  • PEAR installer version 1.4.3 or later
  • Perforce C/C++ API version 2006.2 or later
  • A C++ compiler and tool chain, if building from source code

1.2   Installation

The easiest way to install the Perforce extension is by using the PECL installer:

pecl install perforce

If you're building from source code, should use the --with-perforce configuration option. If your copy of the Perforce C/C++ API hasn't been installed in one of the default locations, you can specify it as a parameter:

--with-perforce=/opt/p4api

More detailed information on installing PECL packages in general can be found in the Installation of PECL Extensions section of the PHP Manual.

1.3   Source Code

This package's source code is hosted in a guest branch of the Perforce Public Depot.

A number of unit tests are included to help maintain correct and expected behavior. The tests can be run using PECL tool's run-tests command:

pecl run-tests -p perforce

Additional unit test contributions are welcome, especially when they increase code coverage or exercise specific use cases.

2   Usage

The Perforce extension provides the PerforceClient class and the PerforceClientUser interface.

All requests to the Perforce server are made through the PerforceClient object, and all responses from the Perforce server are received via methods of the PerforceClientUser interface.

Users must provide their own class which implements the PerforceClientUser interface and then pass an instance of that class to the PerforceClient class's constructor.

class MyClientUser implements PerforceClientUser
{
    ...
}

$ui = new MyClientUser();
$p4 = new PerforceClient($ui);

Before the PerforceClient instance can be used, it must be initialized. This will open the connection to the Perforce server. Any desired non-default connection parameters (such as the clientspec name or the server's port) must be specified before attempting to initialize the connection.

$p4->setClient('ClientspecName');
$p4->setPort('public.perforce.com:1666');

if ($p4->init() === false) {
    die('Failed to initialize Perforce server connection');
}

Once the connection has been initialized, commands can be issued to the server using the setArgs() and run() methods.

$p4->setArgs('Jon_Parise');
$p4->run('users');

The run() method will send the command to the server immediately and then wait for the response. When the response is received, the appropriate method (or methods) on the user's PerforceClientUser class will called.

At the end of the session, the connection should be closed.

$p4->final();

More detailed information on the various client methods is provided in this document's Class Reference section.

3   Class Reference

3.1   The PerforceClient Class

3.1.1   PerforceClient(object $ui)

Creates a new PerforceClient instance which uses the provided object for all user input and output.

3.1.2   bool dropped()

Checks if the connection is no longer usable. This is useful if you want to reuse a client connection for multiple commands and need to make sure that the connection is still alive.

If a dropped connection is detected, the actual error message won't be available until final() is called to completely close the connection.

3.1.3   int final()

Closes the current connection and returns the final number of errors that occurred during the connection's lifetime.

3.1.4   string getCharset()

Gets the current character set.

3.1.5   string getClient()

Gets the current client setting.

3.1.6   string getCwd()

Gets the current working directory as set by setCwd().

3.1.7   string getHost()

Gets the client hostname. If a prior call to setHost() has not been made, calling this function may result in reverse DNS lookup.

3.1.8   string getLanguage()

Gets the current language.

3.1.9   string getOs()

Gets the name of the client operating system. Value operating system names are UNIX, vms, NT, Mac, and null.

3.1.10   string getPassword()

Gets the current password setting.

3.1.11   string getPort()

Gets the current port setting for this connection.

3.1.12   string getUser()

Gets the current user setting.

3.1.13   bool setPort(string $port)

Sets the port to be used for this connection. This must be called prior to creating the connection via init().

3.1.14   string getProtocol(string $protocol)

Gets the current value of a specific protocol being used by this connection. This should only be called after a call to run(); otherwise, incomplete information will be returned.

The list of supported protocols is detailed in the documentation for setProtocol().

This function will only report protocol variables set by the server, not those variables set by the client via calls to setProtocol().

3.1.15   bool init()

Establishes a connection to the server specified by setPort() in preparation for running commands via run().

3.1.16   bool run(string $command)

Runs a Perforce command and returns when it completes. Command arguments must be set separately by calling setArgs(). This must be called prior to creating the connection via init().

3.1.17   bool setUser(string $user)

Sets the user to be used for subsequent commands executed via run().

3.1.18   bool setPassword(string $password)

Sets the password to be used for subsequent commands executed via run().

3.1.19   bool setClient(string $client)

Sets the client to be used for subsequent commands executed via run().

3.1.20   string getConfig()

Gets the name of the current configuration file. If none has been set, the string noconfig will be returned.

3.1.21   bool setArgs(string $arg1[, string ...])

Sets a list of arguments that will be passed to a Perforce command executed using run(). This function must be called for each call to run().

This function accepts either multiple individual arguments or an array of arguments.

3.1.22   bool setCharset(string $charset)

Sets the character set to be used for subsequent commands executed via run().

3.1.23   bool setCwd(string $cwd)

Sets the working directory to be used for subsequent commands executed via run().

3.1.24   bool setHost(string $host)

Sets the hostname to be used for subsequent commands executed via run().

3.1.25   bool setLanguage(string $language)

Sets the language to be used for subsequent commands executed via run().

3.1.26   bool setProg(string $name)

Sets the application or string name for this connection. The program's identity will be reported by the p4 monitor command and recorded in the server's log. This function should be called after init() and prior to calling run().

3.1.27   bool setProtocol(string $protocol, string $value)

Sets special protocols for the server to use for this connection. This must be called prior to creating the connection via init().

Protocol Description
tag Enables tagged output if set to any value.
specstring Enables specially formatted forms if set to any value.
api Specifies a specific server API value for this connection.

3.1.28   bool setTicketFile(string $filename)

Sets the absolute filename of the ticket file to be used for subsequent commands executed via run().

3.2   The PerforceClientUser Interface

3.2.1   void Diff(string $file1, string $file2, boolean $doPage, int $flags)

Handle a two-way diff request.

function Diff($file1, $file2, $doPage, $flags)
{
    if (!empty($_ENV['P4DIFF'])) {
        $diff = $_ENV['P4DIFF'];
    } else if (!empty($_ENV['DIFF'])) {
        $diff = $_ENV['DIFF'];
    } else {
        $this->OutputError(
            'No diff program specified with $P4DIFF or $DIFF.');
    }

    $pager = false;
    if ($doPage) {
        if (!empty($_ENV['P4PAGER'])) {
            $pager = $_ENV['P4PAGER'];
        } else if (!empty($_ENV['PAGER'])) {
            $pager = $_ENV['PAGER'];
        } else {
            $pager = false;
        }
    }

    if ($pager) {
        system("$diff $flags $file1 $file2 | $pager");
    } else {
        system("$diff $flags $file1 $file2");
    }
}

3.2.2   void Edit(string $file)

Handle a file edit request.

function Edit($file)
{
    if (!empty($_ENV['P4EDITOR'])) {
        $editor = $_ENV['P4EDITOR'];
    } else if (!empty($_ENV['EDITOR'])) {
        $editor = $_ENV['EDITOR'];
    } else {
        $editor = 'vi';
    }

    system("$editor $file");
}

3.2.3   void ErrorPause(string $message)

Display an error message and wait for user to respond.

function ErrorPause($message)
{
    $this->OutputError($message);
    fgetc(STDIN);
}

3.2.4   void HandleError(string $message, int $severity)

Handle an error after a failed command.

function HandleError($message, $severity)
{
    fwrite(STDERR, "[$severity] $message\n");
}

3.2.5   void Help(string $message)

Output help text.

function Help($help)
{
    $this->Message(implode("\n", $help));
}

3.2.6   string InputData()

Gather input from the user and return it to the current command.

function InputData()
{
    return fgets(STDIN);
}

3.2.7   void Merge(string $base, string $leg1, string $leg2, string $result)

Handle a merge request.

function Merge($base, $leg1, $leg2, $result)
{
    if (!empty($_ENV['P4MERGE'])) {
        $merge = $_ENV['P4MERGE'];
    } else if (!empty($_ENV['MERGE'])) {
        $merge = $_ENV['MERGE'];
    } else {
        $this->OutputError(
            'No merge program specified with $P4MERGE or $MERGE.');
    }

    system("$merge $base $leg1 $leg2 $result");
}

3.2.8   void Message(string $message, int $severity)

Output information or errors from the current command.

function Message($message, $severity)
{
    $this->OutputInfo(0, $message);
}

3.2.9   void OutputBinary(string $data)

Output binary data.

function OutputBinary($data)
{
    fwrite(STDOUT, $data);
}

3.2.10   void OutputError(string $message)

Display an error message.

function OutputError($message)
{
    fwrite(STDERR, "$message\n");
}

3.2.11   void OutputInfo(int $level, string $data)

Output tabular data.

function OutputInfo($level, $data)
{
    fwrite(STDOUT, $data);
}

3.2.12   void OutputStat(array $tags)

Output an array of file status tags.

function OutputStat($tags)
{
    foreach ($tags as $key => $value) {
        if ($key !== 'func') {
            $this->OutputText('... ' . $key . ' ' . $value . "\n");
        }
    }
}

3.2.13   void OutputText(string $data)

Output textual data.

function OutputText($data)
{
    fwrite(STDOUT, $data);
}

3.2.14   string Prompt(string $message)

Prompt the user for input and return it to the current command.

function Prompt($message)
{
    echo $message;

    return fgets(STDIN);
}

4   Development and Support

4.1   Reporting Problems and Suggestions

If you run into a problem or would like to make a suggestion, please use the PECL Bug Tracker. Feel free to contact me directly for other issues, but please try to use the bug tracker whenever possible so that others in the community will benefit from your feedback and my responses.

4.2   Coming Soon

This section contains a list of "todo" items that will hopefully be addressed in future releases.

  • No items at this time.

If you have feature suggestions, please submit them using the PECL Bug Tracker.