// FIXME: this obviously won't work with remote databases - upstream␊ |
// needs to implement mtn db info in automate at first␊ |
$repo = sprintf(Pluf::f('mtn_repositories'), $this->project->shortname);␊ |
if (!file_exists($repo))␊ |
{␊ |
if (!file_exists($repo)) {␊ |
return 0;␊ |
}␊ |
␊ |
|
{␊ |
try␊ |
{␊ |
$out = $this->stdio->exec(array("interface_version"));␊ |
$out = $this->stdio->exec(array('interface_version'));␊ |
return floatval($out) >= self::$MIN_INTERFACE_VERSION;␊ |
}␊ |
catch (IDF_Scm_Exception $e) {}␊ |
|
}␊ |
// FIXME: we could / should introduce handling of suspended␊ |
// (i.e. dead) branches here by hiding them from the user's eye...␊ |
$out = $this->stdio->exec(array("branches"));␊ |
$out = $this->stdio->exec(array('branches'));␊ |
␊ |
// note: we could expand each branch with one of its head revisions␊ |
// here, but these would soon become bogus anyway and we cannot␊ |
// map multiple head revisions here either, so we just use the␊ |
// selector as placeholder␊ |
$res = array();␊ |
foreach (preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY) as $b)␊ |
{␊ |
foreach (preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY) as $b) {␊ |
$res["h:$b"] = $b;␊ |
}␊ |
␊ |
|
$branch = "*";␊ |
}␊ |
␊ |
if (count($this->_resolveSelector("h:$branch")) == 0)␊ |
{␊ |
if (count($this->_resolveSelector("h:$branch")) == 0) {␊ |
throw new IDF_Scm_Exception(␊ |
"Branch $branch is empty"␊ |
);␊ |
|
*/␊ |
private function _resolveSelector($selector)␊ |
{␊ |
$out = $this->stdio->exec(array("select", $selector));␊ |
$out = $this->stdio->exec(array('select', $selector));␊ |
return preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY);␊ |
}␊ |
␊ |
|
$pos = 0;␊ |
$stanzas = array();␊ |
␊ |
while ($pos < strlen($in))␊ |
{␊ |
while ($pos < strlen($in)) {␊ |
$stanza = array();␊ |
while ($pos < strlen($in))␊ |
{␊ |
while ($pos < strlen($in)) {␊ |
if ($in[$pos] == "\n") break;␊ |
␊ |
$stanzaLine = array("key" => "", "values" => array(), "hash" => null);␊ |
while ($pos < strlen($in))␊ |
{␊ |
$stanzaLine = array('key' => '', 'values' => array(), 'hash' => null);␊ |
while ($pos < strlen($in)) {␊ |
$ch = $in[$pos];␊ |
if ($ch == '"' || $ch == '[') break;␊ |
++$pos;␊ |
|
$stanzaLine['key'] .= $ch;␊ |
}␊ |
␊ |
if ($in[$pos] == '[')␊ |
{␊ |
if ($in[$pos] == '[') {␊ |
++$pos; // opening square bracket␊ |
$stanzaLine['hash'] = substr($in, $pos, 40);␊ |
$pos += 40;␊ |
|
else␊ |
{␊ |
$valCount = 0;␊ |
while ($in[$pos] == '"')␊ |
{␊ |
while ($in[$pos] == '"') {␊ |
++$pos; // opening quote␊ |
$stanzaLine['values'][$valCount] = "";␊ |
while ($pos < strlen($in))␊ |
{␊ |
$stanzaLine['values'][$valCount] = '';␊ |
while ($pos < strlen($in)) {␊ |
$ch = $in[$pos]; $pr = $in[$pos-1];␊ |
if ($ch == '"' && $pr != '\\') break;␊ |
++$pos;␊ |
|
}␊ |
++$pos; // closing quote␊ |
␊ |
if ($in[$pos] == ' ')␊ |
{␊ |
if ($in[$pos] == ' ') {␊ |
++$pos; // space␊ |
++$valCount;␊ |
}␊ |
}␊ |
␊ |
for ($i = 0; $i <= $valCount; $i++)␊ |
{␊ |
for ($i = 0; $i <= $valCount; $i++) {␊ |
$stanzaLine['values'][$i] = str_replace(␊ |
array("\\\\", "\\\""),␊ |
array("\\", "\""),␊ |
|
{␊ |
static $certCache = array();␊ |
␊ |
if (!array_key_exists($rev, $certCache))␊ |
{␊ |
$out = $this->stdio->exec(array("certs", $rev));␊ |
if (!array_key_exists($rev, $certCache)) {␊ |
$out = $this->stdio->exec(array('certs', $rev));␊ |
␊ |
$stanzas = self::_parseBasicIO($out);␊ |
$certs = array();␊ |
foreach ($stanzas as $stanza)␊ |
{␊ |
foreach ($stanzas as $stanza) {␊ |
$certname = null;␊ |
foreach ($stanza as $stanzaline)␊ |
{␊ |
foreach ($stanza as $stanzaline) {␊ |
// luckily, name always comes before value␊ |
if ($stanzaline['key'] == "name")␊ |
{␊ |
if ($stanzaline['key'] == 'name') {␊ |
$certname = $stanzaline['values'][0];␊ |
continue;␊ |
}␊ |
␊ |
if ($stanzaline['key'] == "value")␊ |
{␊ |
if (!array_key_exists($certname, $certs))␊ |
{␊ |
if ($stanzaline['key'] == 'value') {␊ |
if (!array_key_exists($certname, $certs)) {␊ |
$certs[$certname] = array();␊ |
}␊ |
␊ |
|
private function _getUniqueCertValuesFor($revs, $certName, $prefix)␊ |
{␊ |
$certValues = array();␊ |
foreach ($revs as $rev)␊ |
{␊ |
foreach ($revs as $rev) {␊ |
$certs = $this->_getCerts($rev);␊ |
if (!array_key_exists($certName, $certs))␊ |
continue;␊ |
foreach ($certs[$certName] as $certValue)␊ |
{␊ |
foreach ($certs[$certName] as $certValue) {␊ |
$certValues[] = "$prefix$certValue";␊ |
}␊ |
}␊ |
|
private function _getLastChangeFor($file, $startrev)␊ |
{␊ |
$out = $this->stdio->exec(array(␊ |
"get_content_changed", $startrev, $file␊ |
'get_content_changed', $startrev, $file␊ |
));␊ |
␊ |
$stanzas = self::_parseBasicIO($out);␊ |
␊ |
// FIXME: we only care about the first returned content mark␊ |
// everything else seem to be very, very rare cases␊ |
foreach ($stanzas as $stanza)␊ |
{␊ |
foreach ($stanza as $stanzaline)␊ |
{␊ |
if ($stanzaline['key'] == "content_mark")␊ |
{␊ |
foreach ($stanzas as $stanza) {␊ |
foreach ($stanza as $stanzaline) {␊ |
if ($stanzaline['key'] == 'content_mark') {␊ |
return $stanzaline['hash'];␊ |
}␊ |
}␊ |
|
{␊ |
$revs = $this->_resolveSelector($commit);␊ |
if (count($revs) == 0) return array();␊ |
return $this->_getUniqueCertValuesFor($revs, "branch", "h:");␊ |
return $this->_getUniqueCertValuesFor($revs, 'branch', 'h:');␊ |
}␊ |
␊ |
/**␊ |
|
*/␊ |
public function getTags()␊ |
{␊ |
if (isset($this->cache['tags']))␊ |
{␊ |
if (isset($this->cache['tags'])) {␊ |
return $this->cache['tags'];␊ |
}␊ |
␊ |
$out = $this->stdio->exec(array("tags"));␊ |
$out = $this->stdio->exec(array('tags'));␊ |
␊ |
$tags = array();␊ |
$stanzas = self::_parseBasicIO($out);␊ |
foreach ($stanzas as $stanza)␊ |
{␊ |
foreach ($stanzas as $stanza) {␊ |
$tagname = null;␊ |
foreach ($stanza as $stanzaline)␊ |
{␊ |
foreach ($stanza as $stanzaline) {␊ |
// revision comes directly after the tag stanza␊ |
if ($stanzaline['key'] == "tag")␊ |
{␊ |
if ($stanzaline['key'] == 'tag') {␊ |
$tagname = $stanzaline['values'][0];␊ |
continue;␊ |
}␊ |
if ($stanzaline['key'] == "revision")␊ |
{␊ |
if ($stanzaline['key'] == 'revision') {␊ |
// FIXME: warn if multiple revisions have␊ |
// equally named tags␊ |
if (!array_key_exists("t:$tagname", $tags))␊ |
{␊ |
if (!array_key_exists("t:$tagname", $tags)) {␊ |
$tags["t:$tagname"] = $tagname;␊ |
}␊ |
break;␊ |
|
{␊ |
$revs = $this->_resolveSelector($commit);␊ |
if (count($revs) == 0) return array();␊ |
return $this->_getUniqueCertValuesFor($revs, "tag", "t:");␊ |
return $this->_getUniqueCertValuesFor($revs, 'tag', 't:');␊ |
}␊ |
␊ |
/**␊ |
|
public function getTree($commit, $folder='/', $branch=null)␊ |
{␊ |
$revs = $this->_resolveSelector($commit);␊ |
if (count($revs) == 0)␊ |
{␊ |
if (count($revs) == 0) {␊ |
return array();␊ |
}␊ |
␊ |
$out = $this->stdio->exec(array(␊ |
"get_manifest_of", $revs[0]␊ |
'get_manifest_of', $revs[0]␊ |
));␊ |
␊ |
$files = array();␊ |
$stanzas = self::_parseBasicIO($out);␊ |
$folder = $folder == '/' || empty($folder) ? '' : $folder.'/';␊ |
␊ |
foreach ($stanzas as $stanza)␊ |
{␊ |
if ($stanza[0]['key'] == "format_version")␊ |
foreach ($stanzas as $stanza) {␊ |
if ($stanza[0]['key'] == 'format_version')␊ |
continue;␊ |
␊ |
$path = $stanza[0]['values'][0];␊ |
|
$file['fullpath'] = $path;␊ |
$file['efullpath'] = self::smartEncode($path);␊ |
␊ |
if ($stanza[0]['key'] == "dir")␊ |
{␊ |
$file['type'] = "tree";␊ |
if ($stanza[0]['key'] == 'dir') {␊ |
$file['type'] = 'tree';␊ |
$file['size'] = 0;␊ |
}␊ |
else␊ |
{␊ |
$file['type'] = "blob";␊ |
$file['type'] = 'blob';␊ |
$file['hash'] = $stanza[1]['hash'];␊ |
$file['size'] = strlen($this->getFile((object)$file));␊ |
}␊ |
␊ |
$rev = $this->_getLastChangeFor($file['fullpath'], $revs[0]);␊ |
if ($rev !== null)␊ |
{␊ |
if ($rev !== null) {␊ |
$file['rev'] = $rev;␊ |
$certs = $this->_getCerts($rev);␊ |
␊ |
|
$scm = IDF_Scm::get($project);␊ |
$branch = $scm->getMainBranch();␊ |
␊ |
if (!empty($commit))␊ |
{␊ |
if (!empty($commit)) {␊ |
$revs = $scm->_resolveSelector($commit);␊ |
if (count($revs) > 0)␊ |
{␊ |
if (count($revs) > 0) {␊ |
$certs = $scm->_getCerts($revs[0]);␊ |
// for the very seldom case that a revision␊ |
// has no branch certificate␊ |
if (count($certs['branch']) == 0)␊ |
{␊ |
$branch = "*";␊ |
if (count($certs['branch']) == 0) {␊ |
$branch = '*';␊ |
}␊ |
else␊ |
{␊ |
|
}␊ |
␊ |
$remote_url = Pluf::f('mtn_remote_url', '');␊ |
if (empty($remote_url))␊ |
{␊ |
if (empty($remote_url)) {␊ |
return '';␊ |
}␊ |
␊ |
return sprintf($remote_url, $project->shortname)."?".$branch;␊ |
return sprintf($remote_url, $project->shortname).'?'.$branch;␊ |
}␊ |
␊ |
/**␊ |
|
*/␊ |
public static function factory($project)␊ |
{␊ |
if (!array_key_exists($project->shortname, self::$instances))␊ |
{␊ |
if (!array_key_exists($project->shortname, self::$instances)) {␊ |
self::$instances[$project->shortname] =␊ |
new IDF_Scm_Monotone($project);␊ |
}␊ |
|
return false;␊ |
␊ |
$out = $this->stdio->exec(array(␊ |
"get_manifest_of", $revs[0]␊ |
'get_manifest_of', $revs[0]␊ |
));␊ |
␊ |
$files = array();␊ |
$stanzas = self::_parseBasicIO($out);␊ |
␊ |
foreach ($stanzas as $stanza)␊ |
{␊ |
if ($stanza[0]['key'] == "format_version")␊ |
foreach ($stanzas as $stanza) {␊ |
if ($stanza[0]['key'] == 'format_version')␊ |
continue;␊ |
␊ |
$path = $stanza[0]['values'][0];␊ |
|
$file = array();␊ |
$file['fullpath'] = $path;␊ |
␊ |
if ($stanza[0]['key'] == "dir")␊ |
{␊ |
if ($stanza[0]['key'] == "dir") {␊ |
$file['type'] = "tree";␊ |
$file['hash'] = null;␊ |
$file['size'] = 0;␊ |
}␊ |
else␊ |
{␊ |
$file['type'] = "blob";␊ |
$file['type'] = 'blob';␊ |
$file['hash'] = $stanza[1]['hash'];␊ |
$file['size'] = strlen($this->getFile((object)$file));␊ |
}␊ |
|
$file['file'] = $pathinfo['basename'];␊ |
␊ |
$rev = $this->_getLastChangeFor($file['fullpath'], $revs[0]);␊ |
if ($rev !== null)␊ |
{␊ |
if ($rev !== null) {␊ |
$file['rev'] = $rev;␊ |
$certs = $this->_getCerts($rev);␊ |
␊ |
|
public function getFile($def, $cmd_only=false)␊ |
{␊ |
// this won't work with remote databases␊ |
if ($cmd_only)␊ |
{␊ |
if ($cmd_only) {␊ |
throw new Pluf_Exception_NotImplemented();␊ |
}␊ |
␊ |
return $this->stdio->exec(array("get_file", $def->hash));␊ |
return $this->stdio->exec(array('get_file', $def->hash));␊ |
}␊ |
␊ |
/**␊ |
|
*/␊ |
private function _getDiff($target, $source = null)␊ |
{␊ |
if (empty($source))␊ |
{␊ |
if (empty($source)) {␊ |
$source = "p:$target";␊ |
}␊ |
␊ |
|
$targets = $this->_resolveSelector($target);␊ |
$sources = $this->_resolveSelector($source);␊ |
␊ |
if (count($targets) == 0 || count($sources) == 0)␊ |
{␊ |
return "";␊ |
if (count($targets) == 0 || count($sources) == 0) {␊ |
return '';␊ |
}␊ |
␊ |
// if target contains a root revision, we cannot produce a diff␊ |
if (empty($sources[0]))␊ |
{␊ |
return "";␊ |
if (empty($sources[0])) {␊ |
return '';␊ |
}␊ |
␊ |
return $this->stdio->exec(␊ |
array("content_diff"),␊ |
array("r" => array($sources[0], $targets[0]))␊ |
array('content_diff'),␊ |
array('r' => array($sources[0], $targets[0]))␊ |
);␊ |
}␊ |
␊ |
|
$certs = $this->_getCerts($revs[0]);␊ |
␊ |
// FIXME: this assumes that author, date and changelog are always given␊ |
$res['author'] = implode(", ", $certs['author']);␊ |
$res['author'] = implode(', ', $certs['author']);␊ |
␊ |
$dates = array();␊ |
foreach ($certs['date'] as $date)␊ |
|
*/␊ |
public function isCommitLarge($commit=null)␊ |
{␊ |
if (empty($commit))␊ |
{␊ |
$commit = "h:"+$this->getMainBranch();␊ |
if (empty($commit)) {␊ |
$commit = 'h:'.$this->getMainBranch();␊ |
}␊ |
␊ |
$revs = $this->_resolveSelector($commit);␊ |
|
return false;␊ |
␊ |
$out = $this->stdio->exec(array(␊ |
"get_revision", $revs[0]␊ |
'get_revision', $revs[0]␊ |
));␊ |
␊ |
$newAndPatchedFiles = 0;␊ |
$stanzas = self::_parseBasicIO($out);␊ |
␊ |
foreach ($stanzas as $stanza)␊ |
{␊ |
if ($stanza[0]['key'] == "patch" || $stanza[0]['key'] == "add_file")␊ |
foreach ($stanzas as $stanza) {␊ |
if ($stanza[0]['key'] == 'patch' || $stanza[0]['key'] == 'add_file')␊ |
$newAndPatchedFiles++;␊ |
}␊ |
␊ |
|
$initialBranches = array();␊ |
$logs = array();␊ |
␊ |
while (!empty($horizont) && $n > 0)␊ |
{␊ |
if (count($horizont) > 1)␊ |
{␊ |
$out = $this->stdio->exec(array("toposort") + $horizont);␊ |
while (!empty($horizont) && $n > 0) {␊ |
if (count($horizont) > 1) {␊ |
$out = $this->stdio->exec(array('toposort') + $horizont);␊ |
$horizont = preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY);␊ |
}␊ |
␊ |
|
$certs = $this->_getCerts($rev);␊ |
␊ |
// read in the initial branches we should follow␊ |
if (count($initialBranches) == 0)␊ |
{␊ |
if (count($initialBranches) == 0) {␊ |
$initialBranches = $certs['branch'];␊ |
}␊ |
␊ |
// only add it to our log if it is on one of the initial branches␊ |
if (count(array_intersect($initialBranches, $certs['branch'])) > 0)␊ |
{␊ |
if (count(array_intersect($initialBranches, $certs['branch'])) > 0) {␊ |
--$n;␊ |
␊ |
$log = array();␊ |
|
$logs[] = (object)$log;␊ |
}␊ |
␊ |
$out = $this->stdio->exec(array("parents", $rev));␊ |
$out = $this->stdio->exec(array('parents', $rev));␊ |
$horizont += preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY);␊ |
}␊ |
␊ |