|
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 |