Perforce Chronicle 2012.2/486814
API Documentation
|
Abstract class for Perforce Connection implementations. More...
Public Member Functions | |
__construct ($port=null, $user=null, $client=null, $password=null, $ticket=null) | |
Create a P4_Connection_Interface instance. | |
_handleError ($result) | |
This function will throw the appropriate exception for the error(s) found in the passed result object. | |
addDisconnectCallback ($callback, $persistent=false) | |
Add a function to run when connection is closed. | |
batchArgs (array $arguments, array $prefixArgs=null, array $suffixArgs=null, $groupSize=1) | |
Return arguments split into chunks (batches) where each batch contains as many arguments as possible to not exceed ARG_MAX or OPTION_LIMIT. | |
clearDisconnectCallbacks () | |
Clear disconnect callbacks. | |
clearInfo () | |
Clear the info cache. | |
connect () | |
Connect to a Perforce Server. | |
disconnect () | |
Run disconnect callbacks. | |
getAppName () | |
Get the application name being reported to the server. | |
getArgMax () | |
Get the maximum allowable length of all command arguments. | |
getCharset () | |
Retrieves the character set used by this connection. | |
getClient () | |
Return the p4 user's client. | |
getClientRoot () | |
Get the current client's root directory with no trailing slash. | |
getHost () | |
Retrieves the client host set for this connection. | |
getInfo () | |
Return an array of connection information. | |
getPassword () | |
Retrieves the password set for this perforce connection. | |
getPort () | |
Return the p4 port. | |
getSecurityLevel () | |
Get the server's security level. | |
getTicket () | |
Retrieves the ticket set for this perforce connection. | |
getUser () | |
Return the name of the p4 user. | |
isCaseSensitive () | |
Check if the server we are connected to is case sensitive. | |
isSuperUser () | |
Check if the user we are connected as has super user privileges. | |
login () | |
Authenticate the user with 'p4 login'. | |
run ($command, $params=array(), $input=null, $tagged=true) | |
Executes the specified command and returns a perforce result object. | |
runDisconnectCallbacks () | |
Run disconnect callbacks. | |
setAppName ($name) | |
Set the name of the application that is using this connection. | |
setCharset ($charset) | |
Sets the character set to use for this perforce connection. | |
setClient ($client) | |
Set the p4 user's client. | |
setHost ($host) | |
Sets the client host name overriding the environment. | |
setPassword ($password) | |
Sets the password to use for this perforce connection. | |
setPort ($port) | |
Set the p4 port. | |
setTicket ($ticket) | |
Sets the ticket to use for this perforce connection. | |
setUser ($user) | |
Set the name of the p4 user. | |
Static Public Member Functions | |
static | escapeArg ($arg) |
Escape a string for use as a command argument. | |
Public Attributes | |
const | DEFAULT_CHARSET = 'utf8unchecked' |
const | LOG_MAX_STRING_LENGTH = 1024 |
const | OPTION_LIMIT = 256 |
Protected Member Functions | |
_connect () | |
Does real work of establishing connection. | |
_prepareInput ($input, $command) | |
Prepare input for passing to Perforce. | |
_run ($command, $params=array(), $input=null, $tagged=true) | |
Actually issues a command. | |
Protected Attributes | |
$_appName | |
$_charset | |
$_client | |
$_disconnectCallbacks = array() | |
$_host | |
$_info | |
$_password | |
$_port | |
$_ticket | |
$_user |
Abstract class for Perforce Connection implementations.
P4_Connection_Abstract::__construct | ( | $ | port = null , |
$ | user = null , |
||
$ | client = null , |
||
$ | password = null , |
||
$ | ticket = null |
||
) |
Create a P4_Connection_Interface instance.
string | $port | optional - the port to connect to. |
string | $user | optional - the user to connect as. |
string | $client | optional - the client spec to use. |
string | $password | optional - the password to use. |
string | $ticket | optional - a ticket to use. |
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_Extension.
{ $this->setPort($port); $this->setUser($user); $this->setClient($client); $this->setPassword($password); $this->setTicket($ticket); // ensure we disconnect on shutdown. P4_Environment::addShutdownCallback( array($this, 'disconnect') ); }
P4_Connection_Abstract::_connect | ( | ) | [abstract, protected] |
Does real work of establishing connection.
Called by connect().
P4_Connection_ConnectException | if the connection fails. |
Reimplemented in P4_Connection_CommandLine, and P4_Connection_Extension.
P4_Connection_Abstract::_handleError | ( | $ | result | ) |
This function will throw the appropriate exception for the error(s) found in the passed result object.
P4_Result | $result | The result containing errors |
{ $message = "Command failed: " . implode("\n", $result->getErrors()); // create appropriate exception based on error condition if (preg_match("/must (sync\/ )?(be )?resolved?/", $message) || preg_match("/Merges still pending/", $message)) { $e = new P4_Connection_ConflictException($message); } else { $e = new P4_Connection_CommandException($message); } $e->setConnection($this); $e->setResult($result); throw $e; }
P4_Connection_Abstract::_prepareInput | ( | $ | input, |
$ | command | ||
) | [abstract, protected] |
Prepare input for passing to Perforce.
string | array | $input | the input to prepare for p4. |
string | $command | the command to prepare input for. |
Reimplemented in P4_Connection_CommandLine, and P4_Connection_Extension.
P4_Connection_Abstract::_run | ( | $ | command, |
$ | params = array() , |
||
$ | input = null , |
||
$ | tagged = true |
||
) | [abstract, protected] |
Actually issues a command.
Called by run() to perform the dirty work.
string | $command | the command to run. |
array | $params | optional - arguments. |
array | string | $input | optional - input for the command - should be provided in array form when writing perforce spec records. |
boolean | $tagged | optional - true/false to enable/disable tagged output. defaults to true. |
Reimplemented in P4_Connection_CommandLine, and P4_Connection_Extension.
P4_Connection_Abstract::addDisconnectCallback | ( | $ | callback, |
$ | persistent = false |
||
) |
Add a function to run when connection is closed.
Callbacks are removed after they are executed unless persistent is set to true.
callable | $callback | the function to execute on disconnect (will be passed connection). |
bool | $persistent | optional - defaults to false - set to true to run callback on repeated disconnects. |
Implements P4_Connection_Interface.
{ if (!is_callable($callback)) { throw new InvalidArgumentException( "Cannot add disconnect callback. Not callable" ); } $this->_disconnectCallbacks[] = array( 'callback' => $callback, 'persistent' => $persistent ); return $this; }
P4_Connection_Abstract::batchArgs | ( | array $ | arguments, |
array $ | prefixArgs = null , |
||
array $ | suffixArgs = null , |
||
$ | groupSize = 1 |
||
) |
Return arguments split into chunks (batches) where each batch contains as many arguments as possible to not exceed ARG_MAX or OPTION_LIMIT.
ARG_MAX is a character limit that affects command line programs (p4). OPTION_LIMIT is a server-side limit on the number of flags (e.g. '-n').
array | $arguments | list of arguments to split into chunks. |
array | null | $prefixArgs | arguments to begin all batches with. |
array | null | $suffixArgs | arguments to end all batches with. |
int | $groupSize | keep arguments together in groups of this size for example, when clearing attributes you want to keep pairs of -n and attr-name together. |
P4_Exception | if a argument (or set of arguments) exceed arg-max. |
Implements P4_Connection_Interface.
{ $argMax = $this->getArgMax(); // determine size of leading and trailing arguments. $initialLength = 0; $initialOptions = 0; $prefixArgs = (array) $prefixArgs; $suffixArgs = (array) $suffixArgs; foreach (array_merge($prefixArgs, $suffixArgs) as $argument) { // if we have an arg-max limit, determine length of common args. // compute length by adding length of escaped argument + 1 space if ($argMax) { $initialLength += strlen(static::escapeArg($argument)) + 1; } // if the first character is a dash ('-'), it's an option if (substr($argument, 0, 1) === '-') { $initialOptions++; } } $batches = array(); while (!empty($arguments)) { // determine how many arguments we can move into this batch. $count = 0; $length = $initialLength; $options = $initialOptions; foreach ($arguments as $argument) { // if we have an arg-max limit, enforce it. // compute length by adding length of escaped argument + 1 space if ($argMax) { $length += strlen(static::escapeArg($argument)) + 1; // if we exceed arg-max, break if ($length >= $argMax) { break; } } // if we exceed the option-limit, break if ($options > static::OPTION_LIMIT) { break; } // if the first character is a dash ('-'), it's an option if (substr($argument, 0, 1) === '-') { $options++; } $count++; } // adjust count down to largest divisible group size // and move that number of arguments into this batch. $count -= $count % $groupSize; $batches[] = array_merge($prefixArgs, array_splice($arguments, 0, $count), $suffixArgs); // handle the case of a given argument group not fitting in a batch // this informs the caller of indivisble args and avoids infinite loops if (!empty($arguments) && $count < $groupSize) { throw new P4_Exception( "Cannot batch arguments. Arguments exceed arg-max and/or option-limit." ); } } return $batches; }
P4_Connection_Abstract::clearDisconnectCallbacks | ( | ) |
Clear disconnect callbacks.
{
$this->_disconnectCallbacks = array();
return $this;
}
P4_Connection_Abstract::clearInfo | ( | ) |
Clear the info cache.
This method is primarily used during testing, and would not normally be used.
{
$this->_info = null;
return $this;
}
P4_Connection_Abstract::connect | ( | ) |
Connect to a Perforce Server.
Hands off to _connect() for the actual mechanics of connecting.
P4_Connection_ConnectException | if the connection fails. |
Implements P4_Connection_Interface.
{ if (!$this->isConnected()) { // refuse to connect if no port or no user set. if (!strlen($this->getPort()) || !strlen($this->getUser())) { throw new P4_Connection_ConnectException( "Cannot connect. You must specify both a port and a user." ); } $this->_connect(); } return $this; }
P4_Connection_Abstract::disconnect | ( | ) |
Run disconnect callbacks.
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_CommandLine, and P4_Connection_Extension.
{ return $this->runDisconnectCallbacks(); }
static P4_Connection_Abstract::escapeArg | ( | $ | arg | ) | [static] |
Escape a string for use as a command argument.
Escaping is a no-op for the abstract implementation, but is needed by batchArgs.
string | $arg | the string to escape |
Reimplemented in P4_Connection_CommandLine.
{
return $arg;
}
P4_Connection_Abstract::getAppName | ( | ) |
Get the application name being reported to the server.
Implements P4_Connection_Interface.
{
return $this->_appName;
}
P4_Connection_Abstract::getArgMax | ( | ) |
Get the maximum allowable length of all command arguments.
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_CommandLine.
{
return 0;
}
P4_Connection_Abstract::getCharset | ( | ) |
Retrieves the character set used by this connection.
Implements P4_Connection_Interface.
{
return $this->_charset;
}
P4_Connection_Abstract::getClient | ( | ) |
Return the p4 user's client.
Implements P4_Connection_Interface.
{
return $this->_client;
}
P4_Connection_Abstract::getClientRoot | ( | ) |
Get the current client's root directory with no trailing slash.
Implements P4_Connection_Interface.
{ $info = $this->getInfo(); if (isset($info['clientRoot'])) { return rtrim($info['clientRoot'], '/\\'); } return false; }
P4_Connection_Abstract::getHost | ( | ) |
Retrieves the client host set for this connection.
Implements P4_Connection_Interface.
{
return $this->_host;
}
P4_Connection_Abstract::getInfo | ( | ) |
Return an array of connection information.
Due to caching, server date may be stale.
Implements P4_Connection_Interface.
{ // if info cache is populated and connection is up, return cached info. if (isset($this->_info) && $this->isConnected()) { return $this->_info; } // run p4 info. $result = $this->run("info"); $this->_info = array(); // gather all data (multiple arrays returned when connecting through broker). foreach ($result->getData() as $data) { $this->_info += $data; } return $this->_info; }
P4_Connection_Abstract::getPassword | ( | ) |
Retrieves the password set for this perforce connection.
Implements P4_Connection_Interface.
{
return $this->_password;
}
P4_Connection_Abstract::getPort | ( | ) |
Return the p4 port.
Implements P4_Connection_Interface.
{
return $this->_port;
}
P4_Connection_Abstract::getSecurityLevel | ( | ) |
Get the server's security level.
Implements P4_Connection_Interface.
{ if (!P4_Counter::exists('security', $this)) { return 0; } return (int) P4_Counter::fetch('security', $this)->getValue(); }
P4_Connection_Abstract::getTicket | ( | ) |
Retrieves the ticket set for this perforce connection.
Implements P4_Connection_Interface.
{
return $this->_ticket;
}
P4_Connection_Abstract::getUser | ( | ) |
Return the name of the p4 user.
Implements P4_Connection_Interface.
{
return $this->_user;
}
P4_Connection_Abstract::isCaseSensitive | ( | ) |
Check if the server we are connected to is case sensitive.
P4_Exception | if unable to determine server case handling. |
Implements P4_Connection_Interface.
{ $info = $this->getInfo(); // throw exception if case handling unknown. if (!isset($info['caseHandling'])) { throw new P4_Exception("Cannot determine server case-handling."); } return $info['caseHandling'] === 'sensitive'; }
P4_Connection_Abstract::isSuperUser | ( | ) |
Check if the user we are connected as has super user privileges.
Implements P4_Connection_Interface.
{ try { $result = $this->run("protects", "-m"); } catch (P4_Connection_CommandException $e) { // if protections table is empty, everyone is super. $errors = $e->getResult()->getErrors(); if (stristr($errors[0], "empty")) { return true; } else if (stristr($errors[0], "password must be set")) { return false; } throw $e; } if ($result->getData(0, "permMax") == "super") { return true; } else { return false; } }
P4_Connection_Abstract::login | ( | ) |
Authenticate the user with 'p4 login'.
P4_Connection_LoginException | if login fails. |
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_Extension.
{ // ensure user name is set. if (!strlen($this->getUser())) { throw new P4_Connection_LoginException( "Login failed. Username is empty.", P4_Connection_LoginException::IDENTITY_AMBIGUOUS ); } // try to login. try { $result = $this->run('login', '-p', $this->_password ?: ''); } catch (P4_Connection_CommandException $e) { // user doesn't exist. if (stristr($e->getMessage(), "doesn't exist") || stristr($e->getMessage(), "has not been enabled by 'p4 protect'") ) { throw new P4_Connection_LoginException( "Login failed. " . $e->getMessage(), P4_Connection_LoginException::IDENTITY_NOT_FOUND ); } // invalid password. if (stristr($e->getMessage(), "password invalid")) { throw new P4_Connection_LoginException( "Login failed. " . $e->getMessage(), P4_Connection_LoginException::CREDENTIAL_INVALID ); } // generic login exception. throw new P4_Connection_LoginException( "Login failed. " . $e->getMessage() ); } // check if no password set for this user. // fail if a password was provided - succeed otherwise. if (stristr($result->getData(0), "no password set for this user")) { if ($this->_password) { throw new P4_Connection_LoginException( "Login failed. " . $result->getData(0), P4_Connection_LoginException::CREDENTIAL_INVALID ); } else { return null; } } // capture ticket from output. $this->_ticket = $result->getData(0); // if ticket wasn't captured correctly, fail with unknown code. if (!$this->_ticket) { throw new P4_Connection_LoginException( "Login failed. Unable to capture login ticket." ); } return $this->_ticket; }
P4_Connection_Abstract::run | ( | $ | command, |
$ | params = array() , |
||
$ | input = null , |
||
$ | tagged = true |
||
) |
Executes the specified command and returns a perforce result object.
No need to call connect() first. Run will connect automatically.
Performs common pre/post-run work. Hands off to _run() for the actual mechanics of running commands.
string | $command | the command to run. |
array | string | $params | optional - one or more arguments. |
array | string | $input | optional - input for the command - should be provided in array form when writing perforce spec records. |
boolean | $tagged | optional - true/false to enable/disable tagged output. defaults to true. |
Implements P4_Connection_Interface.
{ // establish connection to perforce server. if (!$this->isConnected()) { $this->connect(); } // ensure params is an array. if (!is_array($params)) { if (!empty($params)) { $params = array($params); } else { $params = array(); } } // log the start of the command w. params. $message = "P4 (" . spl_object_hash($this) . ") start command: " . $command . " " . implode(" ", $params); P4_Log::log( substr($message, 0, static::LOG_MAX_STRING_LENGTH), P4_Log::DEBUG ); // prepare input for passing to perforce. $input = $this->_prepareInput($input, $command); // defer to sub-classes to actually issue the command. $result = $this->_run($command, $params, $input, $tagged); // log errors - log them and throw an exception. if ($result->hasErrors()) { // if we have no charset, and the command failed because we are // talking to a unicode server, automatically use the default // charset and run the command again. $errors = $result->getErrors(); $needle = 'Unicode server permits only unicode enabled clients.'; if (!$this->getCharset() && stripos($errors[0], $needle) !== false) { $this->setCharset(static::DEFAULT_CHARSET); // run the command again now that we have a charset. return call_user_func_array( array($this, 'run'), func_get_args() ); } // if connect failed due to an untrusted server, trust it and retry $needle = "To allow connection use the 'p4 trust' command"; if (stripos($errors[0], $needle) !== false && !$this->_hasTrusted) { // add a property to avoid re-recursing on this test $this->_hasTrusted = true; // trust the connection as this is the first time we have seen it $this->run('trust', '-y'); // run the command again now that we have trusted it return call_user_func_array( array($this, 'run'), func_get_args() ); } $message = "P4 (" . spl_object_hash($this) . ") command failed: " . implode("\n", $result->getErrors()); P4_Log::log( substr($message, 0, static::LOG_MAX_STRING_LENGTH), P4_Log::ERR ); $this->_handleError($result); } return $result; }
P4_Connection_Abstract::runDisconnectCallbacks | ( | ) |
Run disconnect callbacks.
{ foreach ($this->_disconnectCallbacks as $key => $callback) { call_user_func($callback['callback'], $this); if (!$callback['persistent']) { unset($this->_disconnectCallbacks[$key]); } } return $this; }
P4_Connection_Abstract::setAppName | ( | $ | name | ) |
Set the name of the application that is using this connection.
The application name will be reported to the server and might be necessary to satisfy certain licensing restrictions.
string | null | $name | the app name to report to the server. |
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_Extension.
{
$this->_appName = is_null($name) ? $name : (string) $name;
return $this;
}
P4_Connection_Abstract::setCharset | ( | $ | charset | ) |
Sets the character set to use for this perforce connection.
You should only set a character set when connecting to a 'unicode enabled' server, or when setting the special value of 'none'.
string | $charset | the charset to use (e.g. 'utf8'). |
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_Extension.
{
$this->_charset = $charset;
return $this;
}
P4_Connection_Abstract::setClient | ( | $ | client | ) |
Set the p4 user's client.
Forces a disconnect if already connected.
string | $client | the name of the client workspace to use. |
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_Extension.
{ $validator = new P4_Validate_SpecName; if ($client !== null && !$validator->isValid($client)) { throw new P4_Exception("Client name: " . implode("\n", $validator->getMessages())); } $this->_client = $client; // clear cached p4 info $this->_info = null; return $this; }
P4_Connection_Abstract::setHost | ( | $ | host | ) |
Sets the client host name overriding the environment.
string | null | $host | the host name to use. |
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_Extension.
{
$this->_host = $host;
return $this;
}
P4_Connection_Abstract::setPassword | ( | $ | password | ) |
Sets the password to use for this perforce connection.
string | $password | the password to use as authentication. |
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_Extension.
{
$this->_password = $password;
return $this;
}
P4_Connection_Abstract::setPort | ( | $ | port | ) |
Set the p4 port.
Forces a disconnect if already connected.
string | $port | the port to connect to. |
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_Extension.
{ $this->_port = (string) $port; // disconnect on port change. $this->disconnect(); return $this; }
P4_Connection_Abstract::setTicket | ( | $ | ticket | ) |
Sets the ticket to use for this perforce connection.
Forces a disconnect if already connected.
string | $ticket | the ticket to use as authentication. |
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_Extension.
{ $this->_ticket = $ticket; // disconnect on ticket change. $this->disconnect(); return $this; }
P4_Connection_Abstract::setUser | ( | $ | user | ) |
Set the name of the p4 user.
Forces a disconnect if already connected.
string | $user | the user to connect as. |
Implements P4_Connection_Interface.
Reimplemented in P4_Connection_Extension.
{ $validator = new P4_Validate_SpecName; if ($user !== null && !$validator->isValid($user)) { throw new P4_Exception("Username: " . implode("\n", $validator->getMessages())); } $this->_user = $user; // disconnect on user change. $this->disconnect(); return $this; }
P4_Connection_Abstract::$_appName [protected] |
P4_Connection_Abstract::$_charset [protected] |
P4_Connection_Abstract::$_client [protected] |
P4_Connection_Abstract::$_disconnectCallbacks = array() [protected] |
P4_Connection_Abstract::$_host [protected] |
P4_Connection_Abstract::$_info [protected] |
P4_Connection_Abstract::$_password [protected] |
P4_Connection_Abstract::$_port [protected] |
P4_Connection_Abstract::$_ticket [protected] |
P4_Connection_Abstract::$_user [protected] |
const P4_Connection_Abstract::DEFAULT_CHARSET = 'utf8unchecked' |
const P4_Connection_Abstract::LOG_MAX_STRING_LENGTH = 1024 |
const P4_Connection_Abstract::OPTION_LIMIT = 256 |