- _getLastChangeFor(): drop that, no longer needed

- getTree(), getPathInfo(): use the new extended manifest format
  and save the calls to query file sizes from contents as well
  as the calls to determine the revision in which a file changed
  at last
This commit is contained in:
Thomas Keller 2010-10-04 15:22:57 +00:00
parent 90edbf0d8b
commit d539eaf64b

View File

@ -212,34 +212,6 @@ class IDF_Scm_Monotone extends IDF_Scm
return array_unique($certValues); return array_unique($certValues);
} }
/**
* Returns the revision in which the file has been last changed,
* starting from the start rev
*
* @param string
* @param string
* @return string
*/
private function _getLastChangeFor($file, $startrev)
{
$out = $this->stdio->exec(array(
'get_content_changed', $startrev, $file
));
$stanzas = IDF_Scm_Monotone_BasicIO::parse($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') {
return $stanzaline['hash'];
}
}
}
return null;
}
/** /**
* @see IDF_Scm::inBranches() * @see IDF_Scm::inBranches()
*/ */
@ -297,51 +269,62 @@ class IDF_Scm_Monotone extends IDF_Scm
} }
/** /**
* @see IDF_Scm::getTree() * Takes a single stanza coming from an extended manifest output
* and converts it into a file structure used by IDF
*
* @param string $forceBasedir If given then the element's path is checked
* to be directly beneath the given directory.
* If not, null is returned and the parsing is
* aborted.
* @return array | null
*/ */
public function getTree($commit, $folder='/', $branch=null) private function _fillFileEntry(array $manifestEntry, $forceBasedir = null)
{ {
$revs = $this->_resolveSelector($commit); $fullpath = $manifestEntry[0]['values'][0];
if (count($revs) == 0) { $filename = basename($fullpath);
return array(); $dirname = dirname($fullpath);
$dirname = $dirname == '.' ? '' : $dirname;
if ($forceBasedir !== null && $forceBasedir != $dirname) {
return null;
} }
$out = $this->stdio->exec(array(
'get_manifest_of', $revs[0]
));
$files = array();
$stanzas = IDF_Scm_Monotone_BasicIO::parse($out);
$folder = $folder == '/' || empty($folder) ? '' : $folder.'/';
foreach ($stanzas as $stanza) {
if ($stanza[0]['key'] == 'format_version')
continue;
$path = $stanza[0]['values'][0];
if (!preg_match('#^'.$folder.'([^/]+)$#', $path, $m))
continue;
$file = array(); $file = array();
$file['file'] = $m[1]; $file['file'] = $filename;
$file['fullpath'] = $path; $file['fullpath'] = $fullpath;
$file['efullpath'] = self::smartEncode($path); $file['efullpath'] = self::smartEncode($fullpath);
if ($stanza[0]['key'] == 'dir') { $wanted_mark = '';
if ($manifestEntry[0]['key'] == 'dir') {
$file['type'] = 'tree'; $file['type'] = 'tree';
$file['size'] = 0; $file['size'] = 0;
$wanted_mark = 'path_mark';
} }
else else {
{
$file['type'] = 'blob'; $file['type'] = 'blob';
$file['hash'] = $stanza[1]['hash']; $file['hash'] = $manifestEntry[1]['hash'];
$file['size'] = strlen($this->getFile((object)$file)); $size = 0;
foreach ($manifestEntry as $line) {
if ($line['key'] == 'size') {
$size = $line['values'][0];
break;
}
}
$file['size'] = $size;
$wanted_mark = 'content_mark';
} }
$rev = $this->_getLastChangeFor($file['fullpath'], $revs[0]); $rev_mark = null;
if ($rev !== null) { foreach ($manifestEntry as $line) {
$file['rev'] = $rev; if ($line['key'] == $wanted_mark) {
$certs = $this->_getCerts($rev); $rev_mark = $line['hash'];
break;
}
}
if ($rev_mark !== null) {
$file['rev'] = $rev_mark;
$certs = $this->_getCerts($rev_mark);
// FIXME: this assumes that author, date and changelog are always given // FIXME: this assumes that author, date and changelog are always given
$file['author'] = implode(", ", $certs['author']); $file['author'] = implode(", ", $certs['author']);
@ -360,6 +343,35 @@ class IDF_Scm_Monotone extends IDF_Scm
$file['log'] = $split[0]; $file['log'] = $split[0];
} }
return $file;
}
/**
* @see IDF_Scm::getTree()
*/
public function getTree($commit, $folder='/', $branch=null)
{
$revs = $this->_resolveSelector($commit);
if (count($revs) == 0) {
return array();
}
$out = $this->stdio->exec(array(
'get_extended_manifest_of', $revs[0]
));
$files = array();
$stanzas = IDF_Scm_Monotone_BasicIO::parse($out);
$folder = $folder == '/' || empty($folder) ? '' : $folder;
foreach ($stanzas as $stanza) {
if ($stanza[0]['key'] == 'format_version')
continue;
$file = $this->_fillFileEntry($stanza, $folder);
if ($file === null)
continue;
$files[] = (object) $file; $files[] = (object) $file;
} }
return $files; return $files;
@ -505,7 +517,7 @@ class IDF_Scm_Monotone extends IDF_Scm
return false; return false;
$out = $this->stdio->exec(array( $out = $this->stdio->exec(array(
'get_manifest_of', $revs[0] 'get_extended_manifest_of', $revs[0]
)); ));
$files = array(); $files = array();
@ -515,43 +527,10 @@ class IDF_Scm_Monotone extends IDF_Scm
if ($stanza[0]['key'] == 'format_version') if ($stanza[0]['key'] == 'format_version')
continue; continue;
$path = $stanza[0]['values'][0]; if ($stanza[0]['values'][0] != $file)
if (!preg_match('#^'.$file.'$#', $path, $m))
continue; continue;
$file = array(); $file = $this->_fillFileEntry($stanza);
$file['fullpath'] = $path;
if ($stanza[0]['key'] == "dir") {
$file['type'] = "tree";
$file['hash'] = null;
$file['size'] = 0;
}
else
{
$file['type'] = 'blob';
$file['hash'] = $stanza[1]['hash'];
$file['size'] = strlen($this->getFile((object)$file));
}
$pathinfo = pathinfo($file['fullpath']);
$file['file'] = $pathinfo['basename'];
$rev = $this->_getLastChangeFor($file['fullpath'], $revs[0]);
if ($rev !== null) {
$file['rev'] = $rev;
$certs = $this->_getCerts($rev);
// FIXME: this assumes that author, date and changelog are always given
$file['author'] = implode(", ", $certs['author']);
$dates = array();
foreach ($certs['date'] as $date)
$dates[] = date('Y-m-d H:i:s', strtotime($date));
$file['date'] = implode(', ', $dates);
$file['log'] = implode("\n---\n", $certs['changelog']);
}
return (object) $file; return (object) $file;
} }
return false; return false;