From: Michael M Slusarz Date: Fri, 23 Jan 2009 07:48:18 +0000 (-0700) Subject: Next batch of Chora/Vcs development. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=ee428349f89fd780b6b10366684ba3dba5799377;p=horde.git Next batch of Chora/Vcs development. Big advance in this batch of commits: browsing branches works now, at least for CVS and Git. --- diff --git a/chora/annotate.php b/chora/annotate.php index 7e751302a..79cee551a 100644 --- a/chora/annotate.php +++ b/chora/annotate.php @@ -12,7 +12,7 @@ require_once dirname(__FILE__) . '/lib/base.php'; /* Spawn the file object. */ -$fl = $VC->getFileObject($where, $cache); +$fl = $VC->getFileObject($where, array('cache' => $cache)); Chora::checkError($fl); $rev_ob = $VC->getRevisionObject(); diff --git a/chora/browse.php b/chora/browse.php index aaf209004..049bf6746 100644 --- a/chora/browse.php +++ b/chora/browse.php @@ -125,12 +125,8 @@ if ($atdir) { } /* Showing a file. */ -// TODO - onb is j -$onb = Util::getFormData('onb', 0); -if ($VC->isValidRevision($onb)) { -} - -$fl = $VC->getFileObject($where, $cache); +$onb = Util::getFormData('onb'); +$fl = $VC->getFileObject($where, array('cache' => $cache, 'branch' => $onb)); Chora::checkError($fl); $title = sprintf(_("Revisions for %s"), $where); @@ -147,7 +143,7 @@ foreach ($fl->symrev as $sm => $rv) { $selAllBranches = ''; if ($VC->hasFeature('branches')) { foreach (array_keys($fl->branches) as $sym) { - $selAllBranches .= ''; + $selAllBranches .= ''; } } diff --git a/chora/co.php b/chora/co.php index 0d0efd133..7515782ce 100644 --- a/chora/co.php +++ b/chora/co.php @@ -21,7 +21,7 @@ if ($atdir) { $plain = Util::getFormData('p', 0); /* Create the VC_File object and populate it. */ -$file = $VC->getFileObject($where, $cache); +$file = $VC->getFileObject($where, array('cache' => $cache)); Chora::checkError($file); /* Get the revision number. */ diff --git a/chora/diff.php b/chora/diff.php index 83ef8c0af..08af32f96 100644 --- a/chora/diff.php +++ b/chora/diff.php @@ -12,7 +12,7 @@ require_once dirname(__FILE__) . '/lib/base.php'; /* Spawn the repository and file objects */ -$fl = $VC->getFileObject($where, $cache); +$fl = $VC->getFileObject($where, array('cache' => $cache)); Chora::checkError($fl); $rev_ob = $VC->getRevisionObject(); diff --git a/chora/history.php b/chora/history.php index d1d4a048c..e68d3cd68 100644 --- a/chora/history.php +++ b/chora/history.php @@ -18,58 +18,17 @@ if (!$VC->hasFeature('branches')) { } /* Spawn the file object. */ -$fl = $VC->getFileObject($where, $cache); +$fl = $VC->getFileObject($where, array('cache' => $cache)); Chora::checkError($fl); $rev_ob = $VC->getRevisionObject(); -/* $trunk contains an array of trunk revisions. */ -$trunk = array(); - -/* $branches is a hash with the branch revision as the key, and value - * being an array of revs on that branch. */ -$branches = array(); - -/* Populate $col with a list of all the branch points. */ -foreach ($fl->branches as $rev) { - $branches[$rev] = array(); -} - -/* For every revision, figure out if it is a trunk revision, or - * instead associated with a branch. If trunk, add it to the $trunk - * array. Otherwise, add it to an array in $branches[$branch]. */ -foreach ($fl->logs as $log) { - $rev = $log->queryRevision(); - $baseRev = $rev_ob->strip($rev, 1); - $branchFound = false; - foreach ($fl->branches as $branch => $name) { - if ($branch == $baseRev) { - array_unshift($branches[$branch], $rev); - $branchFound = true; - } - } - /* If its not a branch, then add it to the trunk. */ - /* TODO: this silently drops vendor branches atm! - avsm. */ - if (!$branchFound && $rev_ob->sizeof($rev) == 2) { - array_unshift($trunk, $rev); - } -} - -foreach ($branches as $col => $rows) { - /* If this branch has no actual commits on it, then it's a stub - * branch, and we can remove it for this view. */ - if (!sizeof($rows)) { - unset($branches[$col]); - } -} - $colset = array('#ccdeff', '#ecf', '#fec', '#efc', '#cfd', '#dcdba0'); -$colStack = array(); -$branchColours = array(); +$branch_colors = $colStack = array(); foreach ($branches as $brrev => $brcont) { if (!count($colStack)) { $colStack = $colset; } - $branchColours[$brrev] = array_shift($colset); + $branch_colors[$brrev] = array_shift($colset); } /** @@ -185,7 +144,7 @@ foreach ($grid as $row) { if ($VC->isValidRevision($rev) && ($rev_ob->sizeof($rev) % 2)) { /* This is a branch point, so put the info out. */ - $bg = isset($branchColours[$rev]) ? $branchColours[$rev] : '#e9e9e9'; + $bg = isset($branch_colors[$rev]) ? $branch_colors[$rev] : '#e9e9e9'; $symname = $fl->branches[$rev]; require CHORA_TEMPLATES . '/history/branch_cell.inc'; @@ -193,13 +152,13 @@ foreach ($grid as $row) { /* This is a continuation cell, so render it with the * branch colour. */ $bgbr = $rev_ob->strip(preg_replace('|^\:|', '', $rev), 1); - $bg = isset($branchColours[$bgbr]) ? $branchColours[$bgbr] : '#e9e9e9'; + $bg = isset($branch_colors[$bgbr]) ? $branch_colors[$bgbr] : '#e9e9e9'; require CHORA_TEMPLATES . '/history/blank.inc'; } elseif ($VC->isValidRevision($rev)) { /* This cell contains a revision, so render it. */ $bgbr = $rev_ob->strip($rev, 1); - $bg = isset($branchColours[$bgbr]) ? $branchColours[$bgbr] : '#e9e9e9'; + $bg = isset($branch_colors[$bgbr]) ? $branch_colors[$bgbr] : '#e9e9e9'; $log = $fl->logs[$rev]; $author = Chora::showAuthorName($log->queryAuthor()); $date = strftime('%e %b %Y', $log->queryDate()); diff --git a/chora/stats.php b/chora/stats.php index f54f13faa..f406e3385 100644 --- a/chora/stats.php +++ b/chora/stats.php @@ -11,7 +11,7 @@ require_once dirname(__FILE__) . '/lib/base.php'; -$fl = $VC->getFileObject($where, $cache); +$fl = $VC->getFileObject($where, array('cache' => $cache)); Chora::checkError($fl); $extraLink = Chora::getFileViews(); diff --git a/framework/Vcs/lib/Horde/Vcs.php b/framework/Vcs/lib/Horde/Vcs.php index 627fb6aec..cdc34e368 100644 --- a/framework/Vcs/lib/Horde/Vcs.php +++ b/framework/Vcs/lib/Horde/Vcs.php @@ -105,8 +105,11 @@ class Horde_Vcs /** * Constructor. */ - public function __construct() + public function __construct($params = array()) { + $this->_sourceroot = $params['sourceroot']; + $this->_paths = $params['paths']; + $pos = strrpos(get_class($this), '_'); $this->_driver = substr(get_class($this), $pos + 1); } @@ -293,10 +296,15 @@ class Horde_Vcs return $this->_cache['diff']->availableDiffTypes(); } - public function getFileObject($filename, $cache = null, $quicklog = false) + /** + * $opts: + * 'cache' - (boolean) + * 'quicklog' - (boolean) + */ + public function getFileObject($filename, $opts = array()) { $class = 'Horde_Vcs_File_' . $this->_driver; - $vc_file = new $class($this, $filename, $cache, $quicklog); + $vc_file = new $class($this, $filename, $opts); return $vc_file->getFileObject(); } @@ -750,6 +758,10 @@ class Horde_Vcs_File public $branches = array(); public $revob; + public function getFileObject() + { + } + /** * TODO */ @@ -769,9 +781,19 @@ class Horde_Vcs_File } /** - * Returns the name of the current file as in the repository + * Returns name of the current file without the repository extensions. + * + * @return string Filename without repository extension + */ + function queryName() + { + return $this->name; + } + + /** + * Returns the name of the current file as in the repository. * - * @return string Filename (without the path) + * @return string Filename (without the path). */ public function queryRepositoryName() { diff --git a/framework/Vcs/lib/Horde/Vcs/Cvs.php b/framework/Vcs/lib/Horde/Vcs/Cvs.php index 18a8c2709..81e17940f 100644 --- a/framework/Vcs/lib/Horde/Vcs/Cvs.php +++ b/framework/Vcs/lib/Horde/Vcs/Cvs.php @@ -2,6 +2,13 @@ /** * Horde_Vcs_cvs implementation. * + * Constructor args: + *
+ * 'sourceroot': The source root for this repository
+ * 'paths': Hash with the locations of all necessary binaries: 'rcsdiff',
+ *          'rlog', 'cvsps', 'cvsps_home' and the temp path: 'temp'
+ * 
+ * * Copyright 2000-2009 The Horde Project (http://www.horde.org/) * * See the enclosed file COPYING for license information (LGPL). If you @@ -27,24 +34,6 @@ class Horde_Vcs_Cvs extends Horde_Vcs_Rcs protected $_branches = true; /** - * Constructor. - * - * @param array $params Any parameter the class expects. - * Current parameters: - *
-     * 'sourceroot': The source root for this repository
-     * 'paths': Hash with the locations of all necessary binaries: 'rcsdiff',
-     *          'rlog', 'cvsps', 'cvsps_home' and the temp path: 'temp'
-     * 
- */ - public function __construct($params) - { - $this->_sourceroot = $params['sourceroot']; - $this->_paths = $params['paths']; - parent::__construct(); - } - - /** * Returns the temporary file path. * * @return string Temporary file path. @@ -66,12 +55,12 @@ class Horde_Vcs_Cvs extends Horde_Vcs_Rcs /** * TODO */ - public function getFileObject($filename, $cache = null, $quicklog = false) + public function getFileObject($filename, $opts = array()) { if (substr($filename, 0, 1) != '/') { $filename = '/' . $filename; } - return parent::getFileObject($this->sourceroot() . $filename, $cache, $quicklog); + return parent::getFileObject($this->sourceroot() . $filename, $opts); } /** @@ -213,10 +202,10 @@ class Horde_Vcs_Checkout_Cvs extends Horde_Vcs_Checkout * Static function which returns a file pointing to the head of the * requested revision of an RCS file. * - * @param Horde_Vcs_Cvs $rep A repository object - * @param string $fullname Fully qualified pathname of the desired file - * to checkout - * @param string $rev Revision number to check out + * @param Horde_Vcs_Cvs $rep A repository object. + * @param string $fullname Fully qualified pathname of the desired file + * to checkout. + * @param string $rev Revision number to check out. * * @return resource|object Either a PEAR_Error object, or a stream * pointer to the head of the checkout @@ -243,9 +232,9 @@ class Horde_Vcs_Checkout_Cvs extends Horde_Vcs_Checkout * /path/to/filename,v --> standard out * and we check that this is the case and error otherwise */ - $co = fgets($RCS, 1024); - if (!preg_match('/^([\S ]+),v\s+-->\s+st(andar)?d ?out(put)?\s*$/', $co, $regs) || $regs[1].',v' != $fullname) { + if (!preg_match('/^([\S ]+),v\s+-->\s+st(andar)?d ?out(put)?\s*$/', $co, $regs) || + ($regs[1] != $fullname)) { return PEAR::raiseError('Unexpected output from checkout: ' . $co); } @@ -403,7 +392,7 @@ class Horde_Vcs_Directory_Cvs extends Horde_Vcs_Directory } } elseif (@is_file($path) && (substr($name, -2) == ',v')) { /* Spawn a new file object to represent this file. */ - $fl = $this->_rep->getFileObject(substr($path, strlen($this->_rep->sourceroot()), -2), $cache, $quicklog); + $fl = $this->_rep->getFileObject(substr($path, strlen($this->_rep->sourceroot()), -2), array('cache' => $cache, 'quicklog' => $quicklog)); if (is_a($fl, 'PEAR_Error')) { return $fl; } else { @@ -439,28 +428,37 @@ class Horde_Vcs_Directory_Cvs extends Horde_Vcs_Directory */ class Horde_Vcs_File_Cvs extends Horde_Vcs_File { + /* @TODO */ + public $filename; + protected $_branch = ''; + /** * Create a repository file object, and give it information about * what its parent directory and repository objects are. * - * @param string $fl Full path to this file. + * @param TODO $rep TODO + * @param string $fl Full path to this file. + * @param array $opts TODO */ - public function __construct($rep, $fl, $cache = null, $quicklog = false) + public function __construct($rep, $fl, $opts = array()) { $this->rep = $rep; $this->name = basename($fl); $this->dir = dirname($fl); $this->filename = $fl; - $this->cache = $cache; - $this->quicklog = $quicklog; + $this->cache = empty($opts['cache']) ? null : $opts['cache']; + $this->quicklog = !empty($opts['quicklog']); + if (!empty($opts['branch'])) { + $this->_branch = $opts['branch']; + } } public function &getFileObject() { /* Assume file is in the Attic if it doesn't exist. */ - $filename = $this->filename; - if (!@is_file($filename . ',v')) { - $filename = dirname($filename) . '/Attic/' . basename($filename); + $filename = $this->filename . ',v'; + if (!@is_file($filename)) { + $filename = dirname($this->filename) . '/Attic/' . basename($this->filename) . ',v'; } /* The version of the cached data. Increment this whenever the @@ -469,22 +467,22 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File $cacheVersion = 2; $cacheId = $this->rep->sourceroot() . '_n' . $filename . '_f' . (int)$this->quicklog . '_v' . $cacheVersion; - $ctime = time() - filemtime($filename . ',v'); + $ctime = time() - filemtime($filename); if ($this->cache && $this->cache->exists($cacheId, $ctime)) { $fileOb = unserialize($this->cache->get($cacheId, $ctime)); $fileOb->setRepository($this->rep); } else { - $fileOb = new Horde_Vcs_File_Cvs($this->rep, $filename . ',v', $this->cache, $this->quicklog); - $fileOb->setRepository($this->rep); - if (is_a(($result = $fileOb->getBrowseInfo()), 'PEAR_Error')) { + if (is_a(($result = $this->getBrowseInfo()), 'PEAR_Error')) { return $result; } - $fileOb->applySort(Horde_Vcs::SORT_AGE); + $this->applySort(Horde_Vcs::SORT_AGE); if ($this->cache) { - $this->cache->set($cacheId, serialize($fileOb)); + $this->cache->set($cacheId, serialize($this)); } + + $fileOb = $this; } return $fileOb; @@ -495,9 +493,9 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File * * @return boolean True if file is in the Attic, and false otherwise */ - function isDeleted() + public function isDeleted() { - return substr($this->dir, -5) == 'Attic'; + return (substr($this->dir, -5) == 'Attic'); } /** @@ -506,13 +504,12 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File * * @return string Filename without repository extension */ - function queryName() + public function queryName() { return preg_replace('/,v$/', '', $this->name); } - - function queryPreviousRevision($rev) + public function queryPreviousRevision($rev) { $ob = $this->rep->getRevisionObject(); return $ob->prev($rev); @@ -523,7 +520,7 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File * * @return string HEAD revision number */ - function queryHead() + public function queryHead() { return $this->head; } @@ -534,10 +531,10 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File * * @return boolean|object PEAR_Error object on error, or true on success */ - function getBrowseInfo() + public function getBrowseInfo() { /* Check that we are actually in the filesystem. */ - $file = $this->queryFullPath(); + $file = $this->queryFullPath() . ',v'; if (!is_file($file)) { return PEAR::raiseError('File Not Found: ' . $file); } @@ -555,6 +552,7 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File } $accum = $revsym = $symrev = array(); + $rev_ob = $this->rep->getRevisionObject(); $state = 'init'; foreach ($return_array as $line) { @@ -597,9 +595,18 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File // hash. $log = new Horde_Vcs_Log_Cvs($this); $err = $log->processLog($accum); - // TODO: error checks - avsm - $this->logs[$log->queryRevision()] = $log; - $this->revs[] = $log->queryRevision(); + $rev = $log->queryRevision(); + $branch = $log->queryBranch(); + if (empty($this->_branch) || + in_array($this->_branch, $log->queryBranch()) || + (($rev_ob->cmp($rev, $this->branches[$this->_branch]) === -1) && + (empty($branch) || + in_array('HEAD', $branch) || + (strpos($this->branches[$this->_branch], $rev) === 0)))) { + $log->setBranch($branch); + $this->logs[$rev] = $log; + $this->revs[] = $rev; + } $accum = array(); } break; @@ -614,7 +621,7 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File * * @return Fully qualified filename of this object */ - function queryFullPath() + public function queryFullPath() { return $this->dir . '/' . $this->name; } @@ -624,7 +631,7 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File * * @return string Pathname relative to the sourceroot. */ - function queryModulePath() + public function queryModulePath() { return preg_replace('|^'. $this->rep->sourceroot() . '/?(.*),v$|', '\1', $this->queryFullPath()); } @@ -637,7 +644,7 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File * * @return string Odd-digit Branch number */ - function toBranch($rev) + public function toBranch($rev) { /* Check if we have a valid revision number */ $rev_ob = $this->rep->getRevisionObject(); @@ -657,6 +664,54 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File return substr_replace($rev, '.', $end2, ($end - $end2 + 1)); } + /** + * TODO + */ + public function getBranchList() + { +/* +// $trunk contains an array of trunk revisions. +$trunk = array(); + +// $branches is a hash with the branch revision as the key, and value +// being an array of revs on that branch. +$branches = array(); + +// Populate $col with a list of all the branch points. +foreach ($fl->branches as $rev) { + $branches[$rev] = array(); +} + +// For every revision, figure out if it is a trunk revision, or +// instead associated with a branch. If trunk, add it to the $trunk +// array. Otherwise, add it to an array in $branches[$branch]. +foreach ($fl->logs as $log) { + $rev = $log->queryRevision(); + $baseRev = $rev_ob->strip($rev, 1); + $branchFound = false; + foreach ($fl->branches as $branch => $name) { + if ($branch == $baseRev) { + array_unshift($branches[$branch], $rev); + $branchFound = true; + } + } + // If its not a branch, then add it to the trunk. + // TODO: this silently drops vendor branches atm! - avsm. + if (!$branchFound && $rev_ob->sizeof($rev) == 2) { + array_unshift($trunk, $rev); + } +} + +foreach ($branches as $col => $rows) { + // If this branch has no actual commits on it, then it's a stub + // branch, and we can remove it for this view. + if (!sizeof($rows)) { + unset($branches[$col]); + } +} +*/ + } + } /** @@ -667,6 +722,9 @@ class Horde_Vcs_File_Cvs extends Horde_Vcs_File */ class Horde_Vcs_Log_Cvs extends Horde_Vcs_Log { + /* Cached branch info. */ + protected $_branch; + public function processLog($raw) { /* Initialise a simple state machine to parse the output of rlog */ @@ -725,16 +783,24 @@ class Horde_Vcs_Log_Cvs extends Horde_Vcs_Log array(); } + public function setBranch($branch) + { + $this->_branch = $branch; + } + public function queryBranch() { - $key = array_search($this->rev, $this->file->branches); - if ($key) { - return array($key); + if (!empty($this->_branch)) { + return $this->_branch; + } + + $key = array_keys($this->file->branches, $this->rev); + if (!empty($key)) { + return $key; } $rev_ob = $this->file->rep->getRevisionObject(); - $key = array_search($rev_ob->strip($this->rev, 1), $this->file->branches); - return $key ? array($key) : array(); + return array_keys($this->file->branches, $rev_ob->strip($this->rev, 1)); } } diff --git a/framework/Vcs/lib/Horde/Vcs/Git.php b/framework/Vcs/lib/Horde/Vcs/Git.php index 6bbd14e39..b86b4cafd 100644 --- a/framework/Vcs/lib/Horde/Vcs/Git.php +++ b/framework/Vcs/lib/Horde/Vcs/Git.php @@ -2,6 +2,12 @@ /** * Horde_Vcs_Git implementation. * + * Constructor args: + *
+ * 'sourceroot': The source root for this repository
+ * 'paths': Hash with the locations of all necessary binaries: 'git'
+ * 
+ * * Copyright 2008-2009 The Horde Project (http://www.horde.org/) * * See the enclosed file COPYING for license information (LGPL). If you @@ -28,25 +34,20 @@ class Horde_Vcs_Git extends Horde_Vcs protected $_branches = true; /** - * Constructor. - * - * @param array $params Any parameter the class expects. - * Current parameters: - * 'sourceroot': The source root for this - * repository - * 'paths': Hash with the locations of all - * necessary binaries: 'git' + * TODO */ - public function __construct($params) + public function isFile($where) { - $this->_sourceroot = escapeshellcmd($params['sourceroot']); - $this->_paths = $params['paths']; - parent::__construct(); + $command = $this->_rep->getCommand() . ' ls-tree master ' . escapeshellarg($where) . ' 2>&1'; + $entry = array(); + exec($command, $entry); + $data = explode(' ', $entry[0]); + return ($data[1] == 'blob'); } public function getCommand() { - return $this->getPath('git') . ' --git-dir=' . $this->_sourceroot; + return $this->getPath('git') . ' --git-dir=' . escapeshellarg($this->_sourceroot); } public function getCheckout($file, $rev) @@ -257,23 +258,11 @@ class Horde_Vcs_Diff_Git extends Horde_Vcs_Diff private function _getRevisionRange($rep, $file, $r1, $r2) { - $cmd = $rep->getCommand() . ' rev-list ' . $r1 . '..' . $r2 . ' -- ' . escapeshellarg($file->queryModulePath()); - $pipe = popen($cmd, 'r'); - if (!is_resource($pipe)) { - throw new Horde_Vcs_Exception('Unable to run ' . $cmd . ': ' . error_get_last()); - } - + $cmd = $rep->getCommand() . ' rev-list ' . escapeshellarg($r1) . '..' . escapeshellarg($r2) . ' -- ' . escapeshellarg($file->queryModulePath()); $revs = array(); - while (!feof($pipe)) { - if ($rev = trim(fgets($pipe, 4096))) { - $revs[] = $rev; - } - } - - pclose($pipe); - - return $revs; + exec($cmd, $revs); + return array_map($revs, 'trim'); } } @@ -298,7 +287,8 @@ class Horde_Vcs_Directory_Git extends Horde_Vcs_Directory $showattic = false) { // @TODO For now, we're browsing master - $head = trim(shell_exec($this->_rep->getCommand() . ' rev-parse --verify master')); + //$head = trim(shell_exec($this->_rep->getCommand() . ' rev-parse --verify master')); + $head = 'HEAD'; // @TODO can use this to see if we have a valid cache of the tree at this revision $dir = $this->queryDir(); @@ -328,7 +318,7 @@ class Horde_Vcs_Directory_Git extends Horde_Vcs_Directory if ($type == 'tree') { $this->_dirs[] = basename($file); } else { - $this->_files[] = $this->_rep->getFileObject($file, $cache, $quicklog); + $this->_files[] = $this->_rep->getFileObject($file, array('cache' => $cache, 'quicklog' => $quicklog)); } } @@ -348,25 +338,27 @@ class Horde_Vcs_Directory_Git extends Horde_Vcs_Directory class Horde_Vcs_File_Git extends Horde_Vcs_File { /* @TODO */ - protected $_branch = 'master'; + protected $_branch; /** * Create a repository file object, and give it information about * what its parent directory and repository objects are. * - * @param string $fl Full path to this file. + * @param TODO $rep TODO + * @param string $fl Full path to this file. + * @param array $opts TODO */ - public function __construct($rep, $fl, $cache = null, $quicklog = false) + public function __construct($rep, $fl, $opts = array()) { - // FIXME: - $rep->cache = $cache; - $this->rep = $rep; $this->fullname = $fl; $this->name = basename($fl); $this->dir = dirname($fl); - $this->quicklog = $quicklog; - $this->cache = $cache; + $this->cache = empty($opts['cache']) ? null : $opts['cache']; + $this->quicklog = !empty($opts['quicklog']); + if (!empty($opts['branch'])) { + $this->_branch = $opts['branch']; + } } /** @@ -374,52 +366,8 @@ class Horde_Vcs_File_Git extends Horde_Vcs_File */ public function getFileObject() { - $this->getBrowseInfo(); - return $this; - } - - /** - * Get the hash name for this file at a specific revision. - * - * @param string $rev TODO - * - * @return string Commit hash. - */ - public function getHashForRevision($rev) - { - return $this->logs[$rev]->getHashForPath($this->fullname); - } - - /** - * Returns name of the current file without the repository - * extensions (usually ,v) - * - * @return string Filename without repository extension - */ - function queryName() - { - return $this->name; - } - - /** - * Populate the object with information about the revisions logs - * and dates of the file. - */ - function getBrowseInfo() - { // Get the list of revisions that touch this path - // TODO: Gets all revisions - $cmd = $this->rep->getCommand() . ' rev-list --branches -- ' . escapeshellarg($this->fullname) . ' 2>&1'; - $revisions = shell_exec($cmd); - if (substr($revisions, 5) == 'fatal') { - throw new Horde_Vcs_Exception($revisions); - } - - if (!strlen($revisions)) { - throw new Horde_Vcs_Exception('No revisions found'); - } - - $this->revs = explode("\n", trim($revisions)); + $this->revs = $this->_getRevList($this->_branch); foreach ($this->revs as $rev) { $this->logs[$rev] = Horde_Vcs_Log_Git::factory($this, $rev); @@ -439,6 +387,34 @@ class Horde_Vcs_File_Git extends Horde_Vcs_File $line = explode(' ', trim($val), 2); $this->branches[substr($line[1], strrpos($line[1], '/') + 1)] = $line[0]; } + + return $this; + } + + protected function _getRevList($branch) + { + $cmd = $this->rep->getCommand() . ' rev-list ' . (empty($branch) ? '--branches' : $branch) . ' -- ' . escapeshellarg($this->fullname) . ' 2>&1'; + + $revisions = shell_exec($cmd); + if (substr($revisions, 5) == 'fatal') { + throw new Horde_Vcs_Exception($revisions); + } elseif (!strlen($revisions)) { + throw new Horde_Vcs_Exception('No revisions found'); + } + + return explode("\n", trim($revisions)); + } + + /** + * Get the hash name for this file at a specific revision. + * + * @param string $rev Revision string. + * + * @return string Commit hash. + */ + public function getHashForRevision($rev) + { + return $this->logs[$rev]->getHashForPath($this->fullname); } /** @@ -453,6 +429,20 @@ class Horde_Vcs_File_Git extends Horde_Vcs_File : $this->dir . '/' . $this->name; } + /** + * TODO + */ + public function getBranchList() + { + $revs = array(); + + foreach (array_keys($this->branches) as $key) { + $revs[$key] = $this->_getRevList($key); + } + + return $revs; + } + } /** @@ -475,17 +465,17 @@ class Horde_Vcs_Log_Git extends Horde_Vcs_Log $cacheVersion = 1; $cacheId = $file->rep->sourceroot() . '_r' . $rev . '_v' . $cacheVersion; - if ($file->rep->cache && + if ($file->cache && // Individual revisions can be cached forever // return array_keys( - $file->rep->cache->exists($cacheId, 0)) { - $logOb = unserialize($file->rep->cache->get($cacheId, 0)); + $file->cache->exists($cacheId, 0)) { + $logOb = unserialize($file->cache->get($cacheId, 0)); $logOb->setRepository($file->rep); } else { $logOb = new Horde_Vcs_Log_Git($file, $rev); - if ($file->rep->cache) { - $file->rep->cache->set($cacheId, serialize($logOb)); + if ($file->cache) { + $file->cache->set($cacheId, serialize($logOb)); } } @@ -624,16 +614,10 @@ class Horde_Vcs_Patchset_Git extends Horde_Vcs_Patchset /** * Populate the object with information about the patchsets that * this file is involved in. - * - * @return mixed PEAR_Error object on error, or true on success. */ function getPatchsets() { - $fileOb = new Horde_Vcs_File_Git($this->_rep, $this->_file); - if (is_a(($result = $fileOb->getBrowseInfo()), 'PEAR_Error')) { - return $result; - } - + $fileOb = $this->_rep->getFileObject($this->_file); $this->_patchsets = array(); foreach ($fileOb->logs as $rev => $log) { diff --git a/framework/Vcs/lib/Horde/Vcs/Svn.php b/framework/Vcs/lib/Horde/Vcs/Svn.php index 44ce09873..2bd91becf 100644 --- a/framework/Vcs/lib/Horde/Vcs/Svn.php +++ b/framework/Vcs/lib/Horde/Vcs/Svn.php @@ -1,10 +1,13 @@ + * 'sourceroot': The source root for this repository + * 'paths': Hash with the locations of all necessary binaries: 'svn', 'diff' + * + * * Copyright 2000-2009 The Horde Project (http://www.horde.org/) * * See the enclosed file COPYING for license information (LGPL). If you @@ -39,19 +42,10 @@ class Horde_Vcs_Svn extends Horde_Vcs /** * Constructor. * - * @param array $params Any parameter the class expects. - * Current parameters: - *
-     * 'sourceroot': The source root for this repository
-     * 'paths': Hash with the locations of all necessary binaries: 'svn',
-     *          'diff'
-     * 
+ * @param array $params Required parameters (see above). */ - public function __construct($params) + public function __construct($params = array()) { - $this->_sourceroot = $params['sourceroot']; - $this->_paths = $params['paths']; - if (!empty($params['username'])) { $this->_username = $params['username']; } @@ -281,7 +275,7 @@ class Horde_Vcs_Directory_Svn extends Horde_Vcs_Directory } elseif (substr($line, -1) == '/') { $this->_dirs[] = substr($line, 0, -1); } else { - $fl = $this->_rep->getFileObject($this->queryDir() . "/$line", $cache, $quicklog); + $fl = $this->_rep->getFileObject($this->queryDir() . "/$line", array('cache' => $cache, 'quicklog' => $quicklog)); if (is_a($fl, 'PEAR_Error')) { return $fl; } else { @@ -313,16 +307,18 @@ class Horde_Vcs_File_Svn extends Horde_Vcs_File { * Create a repository file object, and give it information about * what its parent directory and repository objects are. * - * @param string $fl Full path to this file. + * @param TODO $rep TODO + * @param string $fl Full path to this file. + * @param array $opts TODO */ - public function __construct($rep, $fl, $cache = null, $quicklog = false) + public function __construct($rep, $fl, $opts = array()) { $this->rep = $rep; $this->name = basename($fl); $this->dir = dirname($fl); $this->filename = $fl; - $this->quicklog = $quicklog; - $this->cache = $cache; + $this->cache = empty($opts['cache']) ? null : $opts['cache']; + $this->quicklog = !empty($opts['quicklog']); } public function getFileObject()