Perforce Chronicle 2012.2/486814
API Documentation
|
Provides volatile (unsubmitted/unversioned) storage in Perforce. More...
Public Member Functions | |
delete () | |
Remove the volatile record. | |
getClientMasquerade () | |
Get the client workspace we are set to masquerade as. | |
save () | |
Save the values in this volatile record to Perforce. | |
setClientMasquerade ($client) | |
Set the client workspace to masquerade as. | |
setId ($id) | |
Set the id of this record. | |
Static Public Member Functions | |
static | exists ($id, $adapter, $masquerade=null) |
Check for the existance of a volatile record by id. | |
static | fetch ($id, $adapter, $masquerade=null) |
Fetch a stored volatile record by id. | |
Public Attributes | |
const | CLIENT = 'volatileClient' |
Protected Member Functions | |
_beginCharade () | |
Begin masquerading as another client/host. | |
_endCharade () | |
Stop masquerading - restore original client/host. | |
_getDepotFile () | |
Get the (depot-syntax formatted) path to this record in Perforce. | |
_populate () | |
Load values into this record from Perforce. | |
_runFree ($command, $params) | |
Run a Perforce command with no exceptions. | |
Protected Attributes | |
$_clientMasquerade = null | |
$_depotFile = null | |
$_originalClient = null | |
$_originalHost = null | |
$_storageSubPath = null |
Provides volatile (unsubmitted/unversioned) storage in Perforce.
This works by creating pending files and setting open attributes on those files. This storage is useful for casual data that has high turn-over or that we simply don't want to make permanent.
Opened attributes can only be viewed by the client workspace that set them. Therefore, this class introduces get/setClientMasquerade() methods that cause it to masquerade as another client workspace when executing Perforce commands.
Volatile records have many limitations:
P4Cms_Record_Volatile::_beginCharade | ( | ) | [protected] |
Begin masquerading as another client/host.
{ // nothing to do if not masquerading. $masquerade = $this->getClientMasquerade(); if (!$masquerade) { return; } $adapter = $this->getAdapter(); $p4 = $adapter->getConnection(); // clobber the current client and host, but remember // them so we can restore them afterwards. $this->_originalClient = $p4->getClient(); $this->_originalHost = $p4->getHost(); $p4->setClient($masquerade->getId() ?: $p4->getClient()); $p4->setHost($masquerade->getHost() ?: $p4->getHost()); }
P4Cms_Record_Volatile::_endCharade | ( | ) | [protected] |
Stop masquerading - restore original client/host.
{ // nothing to do if not masquerading. if (!$this->_originalClient) { return; } $adapter = $this->getAdapter(); $p4 = $adapter->getConnection(); $p4->setClient($this->_originalClient); $p4->setHost($this->_originalHost); $this->_originalClient = null; $this->_originalHost = null; }
P4Cms_Record_Volatile::_getDepotFile | ( | ) | [protected] |
Get the (depot-syntax formatted) path to this record in Perforce.
{ // must have an id to get depot file. if (!$this->getId()) { throw new P4Cms_Record_Exception("Cannot get record file path without an id."); } // convert id to depot file syntax if we haven't already. if (!$this->_depotFile) { $adapter = $this->getAdapter(); $subPath = trim($this->_storageSubPath, '/\\'); $subPath = $subPath ? '/' . $subPath . '/' : '/'; $file = $adapter->getBasePath() . $subPath . $this->getId(); $result = $adapter->getConnection()->run('where', $file); $this->_depotFile = $result->getData(0, 'depotFile'); } return $this->_depotFile; }
P4Cms_Record_Volatile::_populate | ( | ) | [protected] |
Load values into this record from Perforce.
Clobbers any existing in-memory values.
{ $file = $this->_getDepotFile(); // masquerade as another client $this->_beginCharade(); try { $result = $this->getAdapter()->getConnection()->run('fstat', array('-Oa', $file)); // extract information if no warings (ie. file exists). if (!$result->hasWarnings()) { $this->_values = array(); foreach ((array) $result->getData(0) as $key => $value) { $parts = explode('-', $key, 2); if (count($parts) !== 2 || $parts[0] !== 'openattr') { continue; } $this->_setValue($parts[1], $value); } } else { // warnings indicate no such record. $e = new P4Cms_Record_NotFoundException( "Cannot fetch record: " . $this->getId() . ". No matching record." ); } } catch (Exception $e) { // look away! } // restore original client. $this->_endCharade(); // if an exception occurred, throw it now. if (isset($e)) { throw $e; } return $this; }
P4Cms_Record_Volatile::_runFree | ( | $ | command, |
$ | params | ||
) | [protected] |
Run a Perforce command with no exceptions.
string | $command | the command to run. |
array | string | $params | optional - one or more arguments. |
{ $adapter = $this->getAdapter(); $p4 = $adapter->getConnection(); try { return $p4->run($command, $params); } catch (P4_Exception $e) { return false; } }
P4Cms_Record_Volatile::delete | ( | ) |
Remove the volatile record.
Since volatile records are never submitted, this is actually a 'p4 revert' operation.
{ $file = $this->_getDepotFile(); // masquerade as another client $this->_beginCharade(); try { $this->getAdapter()->getConnection()->run('revert', array('-k', $file)); } catch (Exception $e) { // look away! } // restore original client. $this->_endCharade(); // if an exception occurred, throw it now. if (isset($e)) { throw $e; } return $this; }
static P4Cms_Record_Volatile::exists | ( | $ | id, |
$ | adapter, | ||
$ | masquerade = null |
||
) | [static] |
Check for the existance of a volatile record by id.
string | $id | the id of the record to lookup |
P4Cms_Record_Adapter | $adapter | the storage adapter to use |
P4_Client | string | null | $masquerade | the client to masquerade as |
{ try { static::fetch($id, $adapter, $masquerade); return true; } catch (P4Cms_Record_NotFoundException $e) { return false; } }
static P4Cms_Record_Volatile::fetch | ( | $ | id, |
$ | adapter, | ||
$ | masquerade = null |
||
) | [static] |
Fetch a stored volatile record by id.
string | $id | the id of the record to fetch |
P4Cms_Record_Adapter | $adapter | the storage adapter to use |
P4_Client | string | null | $masquerade | the client to masquerade as |
P4Cms_Record_NotFoundException | if no matching record can be found. |
{ $record = new static; $record->setId($id) ->setAdapter($adapter) ->setClientMasquerade($masquerade) ->_populate(); return $record; }
P4Cms_Record_Volatile::getClientMasquerade | ( | ) |
Get the client workspace we are set to masquerade as.
If no masquerade client has been explicitly set we will fetch/create one based on the presence of a 'volatileClient' property on the storage adapter.
{ // if we already have a client that we're masquerading as, return it. if ($this->_clientMasquerade) { return $this->_clientMasquerade; } // the adapter may specify a volatile client property (the site // branch object does this), if we don't have one early exit. $adapter = $this->getAdapter(); if (!$adapter->hasProperty(static::CLIENT)) { return null; } $p4 = $adapter->getConnection(); $clientId = $adapter->getProperty(static::CLIENT); // try to fetch the volatile client - if it does not exist, create one // based on the adapter's existing client (ie. same view/stream). try { $client = P4_Client::fetch($clientId, $p4); } catch (P4_Spec_NotFoundException $e) { $client = P4_Client::fetch($p4->getClient(), $p4); $client->setId($clientId) ->setDescription("Chronicle generated 'volatile' record client.") ->setRoot(P4_Environment::isWindows() ? "NUL" : "/dev/null") ->touchUpView() ->save(); } $this->_clientMasquerade = $client; return $this->_clientMasquerade; }
P4Cms_Record_Volatile::save | ( | ) |
Save the values in this volatile record to Perforce.
Note that the values are not submitted, only pended.
{ $file = $this->_getDepotFile(); // masquerade as another client $this->_beginCharade(); try { // ensure pending file is opened for add (or edit) // we use flush and -t/k to avoid touching files on disk. $this->_runFree('flush', $file); $this->_runFree('add', array('-t', 'text', $file)); $this->_runFree('edit', array('-kt', 'text', $file)); $params = array(); foreach ($this->_values as $key => $value) { $params[] = "-n"; $params[] = $key; $params[] = "-v"; $params[] = (string) $value; } $params[] = $file; $this->getAdapter()->getConnection()->run('attribute', $params); } catch (Exception $e) { // look away! } // restore original client. $this->_endCharade(); // if an exception occurred, throw it now. if (isset($e)) { throw $e; } return $this; }
P4Cms_Record_Volatile::setClientMasquerade | ( | $ | client | ) |
Set the client workspace to masquerade as.
P4_Client | string | null | $client | the client workspace to masquerade as |
{ // upgrade client to a client object. $client = (!$client instanceof P4_Client && !is_null($client)) ? P4_Client::fetch($client, $this->getAdapter()->getConnection()) : $client; $this->_clientMasquerade = $client; return $this; }
P4Cms_Record_Volatile::setId | ( | $ | id | ) |
Set the id of this record.
Extended to clear depotFile anytime id changes.
mixed | $id | the value of the id of this record. |
Reimplemented from P4Cms_Model.
{ $this->_depotFile = null; return parent::setId($id); }
P4Cms_Record_Volatile::$_clientMasquerade = null [protected] |
P4Cms_Record_Volatile::$_depotFile = null [protected] |
P4Cms_Record_Volatile::$_originalClient = null [protected] |
P4Cms_Record_Volatile::$_originalHost = null [protected] |
P4Cms_Record_Volatile::$_storageSubPath = null [protected] |
Reimplemented in P4Cms_Content_Opened.
const P4Cms_Record_Volatile::CLIENT = 'volatileClient' |