? $conf['options']['introTitle']
: sprintf(_("Source Directory of /%s"), $where);
- $extraLink = $VC->supportsFeature('deleted')
+ $extraLink = $VC->hasFeature('deleted')
? Horde::widget(Chora::url('', $where . '/', array('sa' => ($acts['sa'] ? 0 : 1))), $acts['sa'] ? _("Hide Deleted Files") : _("Show Deleted Files"), 'widget', '', '', $acts['sa'] ? _("Hide _Deleted Files") : _("Show _Deleted Files"))
: '';
}
/* Showing a file. */
-$fl = $VC->getFileObject($where, $cache);
-Chora::checkError($fl);
-$title = sprintf(_("Revisions for %s"), $where);
+// TODO - onb is j
$onb = Util::getFormData('onb', 0);
if ($VC->isValidRevision($onb)) {
- $onb_len = strlen($onb);
- $onb_base = $rev_ob->strip($onb, 1);
- $onb_parents = array();
- while (substr_count($onb_base, '.')) {
- $onb_parents[$onb_base] = true;
- $onb_base = $rev_ob->strip($onb_base, 1);
- }
-} else {
- $onb = null;
}
+$fl = $VC->getFileObject($where, $cache);
+Chora::checkError($fl);
+$title = sprintf(_("Revisions for %s"), $where);
+
$extraLink = Chora::getFileViews();
$first = end($fl->logs);
$diffValueLeft = $first->queryRevision();
}
$selAllBranches = '';
-foreach ($fl->branches as $num => $sym) {
- $selAllBranches .= '<option value="' . $num . '"' . ($num == $onb ? ' selected="selected"' : '') . '>' . $sym . '</option>';
+if ($VC->hasFeature('branches')) {
+ foreach (array_keys($fl->branches) as $sym) {
+ $selAllBranches .= '<option value="' . $sym . '">' . $sym . '</option>';
+ }
}
Horde::addScriptFile('prototype.js', 'horde', true);
$i = 0;
foreach ($fl->logs as $lg) {
$rev = $lg->queryRevision();
- list($branchName, $branchRev) = Chora::getBranch($fl, $rev);
-
- /* Are we tracking a branch? */
- if ($onb) {
- /* If we are on the branch itself, let it through */
- if (substr($rev, 0, $onb_len) != $onb) {
- /* If the revision is on one of the parent branches, and
- * is before the branch was made, let it through. */
- if ((!isset($onb_parents[$branchRev]) && substr_count($rev, '.') > 1) ||
- $rev_ob->cmp($rev, $onb) > 0) {
- continue;
- }
- }
- }
+ $branch_info = Chora::getBranch($fl, $rev);
$textUrl = Chora::url('co', $where, array('r' => $rev));
$commitDate = Chora::formatDate($lg->queryDate());
require CHORA_TEMPLATES . '/log/rev.inc';
- if ($i++ > 100 && !Util::getFormData('all')) {
+ if (($i++ > 100) && !Util::getFormData('all')) {
break;
}
}
Chora::url('co', $where, array('r' => $r, 'p' => 1)), _("Download"));
$tags = Chora::getTags($log, $where);
- list($branchName,) = Chora::getBranch($file, $r);
+ $branch_info = Chora::getBranch($file, $r);
$log_print = Chora::formatLogMessage($log->queryLog());
$author = Chora::showAuthorName($log->queryAuthor(), true);
require_once dirname(__FILE__) . '/lib/base.php';
// Exit if cvsgraph isn't active or it's not supported.
-if (empty($conf['paths']['cvsgraph']) || !$VC->supportsFeature('branches')) {
+if (empty($conf['paths']['cvsgraph']) || !$VC->hasFeature('branches')) {
header('Location: ' . Chora::url('', $where));
exit;
}
$log_messages = array();
foreach ($VC->getRevisionRange($fl, $r1, $r2) as $val) {
if (isset($log[$val])) {
- list($branchname, $branchrev) = Chora::getBranch($fl, $val);
$clog = $log[$val];
$log_messages[] = array(
'rev' => $val,
'msg' => Chora::formatLogMessage($clog->queryLog()),
'author' => Chora::showAuthorName($clog->queryAuthor(), true),
- 'branchRev' => $branchrev,
- 'branchName' => $branchname,
+ 'branchinfo' => Chora::getBranch($fl, $val),
'date' => Chora::formatDate($clog->queryDate()),
'tags' => Chora::getTags($clog, $where),
);
require_once dirname(__FILE__) . '/lib/base.php';
/* Exit if it's not supported. */
-if (!$VC->supportsFeature('branches')) {
+if (!$VC->hasFeature('branches')) {
header('Location: ' . Chora::url('browse', $where));
exit;
}
/* Spawn the file object. */
$fl = $VC->getFileObject($where, $cache);
-$rev_ob = $VC->getRevisionObject();
Chora::checkError($fl);
+$rev_ob = $VC->getRevisionObject();
/* $trunk contains an array of trunk revisions. */
$trunk = array();
$branches = array();
/* Populate $col with a list of all the branch points. */
-foreach ($fl->branches as $rev => $sym) {
+foreach ($fl->branches as $rev) {
$branches[$rev] = array();
}
'', _("_Logs"));
if (!empty($GLOBALS['conf']['paths']['cvsps']) ||
- $GLOBALS['VC']->supportsFeature('patchsets')) {
+ $GLOBALS['VC']->hasFeature('patchsets')) {
$views[] = $current == 'patchsets'
? '<em class="widget">' . _("Patchsets") . '</em>'
: Horde::widget(Chora::url('patchsets', $where), _("Patchsets"),
'widget', '', '', _("_Patchsets"));
}
- if ($GLOBALS['VC']->supportsFeature('branches')) {
+ if ($GLOBALS['VC']->hasFeature('branches')) {
if (empty($GLOBALS['conf']['paths']['cvsgraph'])) {
$views[] = $current == 'history'
? '<em class="widget">' . _("Branches") . '</em>'
* Return branch information for a given revision.
*
* @param Horde_Vcs_File $fl The Horde_Vcs_File object.
- * @param string $rev The filename.
+ * @param string $rev The revision string.
*
- * @return array A 2-member array - branch name and branch revision.
+ * @return array TODO
*/
static public function getBranch($fl, $rev)
{
- $branchName = '';
+ return $GLOBALS['VC']->hasFeature('branches')
+ ? array_keys($fl->branches, $rev)
+ : array();
+
+ /*
$rev_ob = $fl->rep->getRevisionObject();
$branchRev = $rev_ob->strip($rev, 1);
if (isset($fl->branches[$rev])) {
$branchName = $fl->branches[$branchRev];
}
return array($branchName, $branchRev);
+ */
}
/**
$notification->attach('status');
// Cache.
-if (!empty($conf['caching'])) {
+if (empty($conf['caching'])) {
+ $cache = null;
+} else {
$cache = &Horde_Cache::singleton($conf['cache']['driver'], Horde::getDriverConfig('cache', $conf['cache']['driver']));
}
// Exit if cvsps isn't active or it's not a subversion repository.
if (empty($conf['paths']['cvsps']) &&
- !$GLOBALS['VC']->supportsFeature('patchsets')) {
+ !$GLOBALS['VC']->hasFeature('patchsets')) {
header('Location: ' . Chora::url('', $where));
exit;
}
$commitDate = Chora::formatDate($patchset['date']);
$readableDate = Chora::readableTime($patchset['date'], true);
$author = Chora::showAuthorName($patchset['author'], true);
- if ($VC->supportsFeature('patchsets')) {
+ if ($VC->hasFeature('patchsets')) {
// The diff should be from the top of the source tree so as to
// get all files.
$topDir = substr($where, 0, strpos($where, '/', 1));
$dir = dirname($where);
foreach ($patchset['members'] as $member) {
$file = array();
- $mywhere = ($VC->supportsFeature('patchsets')) ? $member['file'] : $dir . '/' . $member['file'];
+ $mywhere = ($VC->hasFeature('patchsets')) ? $member['file'] : $dir . '/' . $member['file'];
$file['file'] = Horde::link(Chora::url('patchsets', $mywhere)) . htmlspecialchars($member['file']) . '</a>';
if ($member['from'] == 'INITIAL') {
$file['from'] = '<ins>' . _("New File") . '</ins>';
<div class="revision_log">
<ul class="revision striped">
<?php if ($author): ?><li><?php echo _("Author:") ?> <?php echo $author ?></li><?php endif; ?>
- <?php if ($branchName): ?><li><?php echo _("Branch:") ?> <strong><a href="<?php echo Chora::url('', $where, array('onb' => $branchRev)) ?>"><?php echo $branchName ?></a></strong></li><?php endif; ?>
+<?php if (!empty($branch_info)): ?>
+ <li><?php echo _("Branch:") ?>
+<?php foreach ($branch_info as $val): ?>
+ <strong><a href="<?php echo Chora::url('', $where, array('onb' => $val)) ?>"><?php echo $val ?></a></strong>
+<?php endforeach; ?>
+ </li>
+<?php endif; ?>
<?php if ($tags): ?><li class="tags"><?php echo _("Tags:") ?> <?php echo implode(', ', $tags) ?></li><?php endif; ?>
</ul>
<?php echo $log_print ?>
<ul class="revision striped">
<?php if (!empty($val['author'])): ?><li><?php echo _("Author:") ?> <?php echo $val['author'] ?></li><?php endif; ?>
<?php if (!empty($val['date'])): ?><li><?php echo _("Date:") ?> <?php echo $val['date'] ?></li><?php endif; ?>
- <?php if (!empty($val['branchName'])): ?><li><?php echo _("Branch:") ?> <strong><a href="<?php echo Chora::url('', $where, array('onb' => $val['branchRev'])) ?>"><?php echo $val['branchName'] ?></a></strong></li><?php endif; ?>
+<?php if (!empty($val['branchinfo'])): ?>
+ <li><?php echo _("Branch:") ?>
+<?php foreach ($val['branchinfo'] as $branchname): ?>
+ <strong><a href="<?php echo Chora::url('', $where, array('onb' => $branchname)) ?>"><?php echo $branchname ?></a></strong>
+<?php endforeach; ?>
+ </li>
+<?php endif; ?>
<?php if (!empty($val['tags'])): ?><li class="tags"><?php echo _("Tags:") ?> <?php echo implode(', ', $val['tags']) ?></li><?php endif; ?>
</ul>
<a href="<?php echo Chora::url('co', $where, array('r' => $val['rev'])) ?>" title="<?php echo htmlspecialchars($val['rev']) ?>"><?php echo htmlspecialchars($rev_ob->abbrev($val['rev'])) ?></a>: <?php echo $val['msg'] ?>
<?php echo _("Location:") ?>
<strong>[ <a href="<?php echo Chora::url('') ?>"><?php echo $conf['options']['sourceRootName'] ?></a> ]
<?php echo Chora::whereMenu() ?></strong>
- <?php if (isset($fl) && isset($onb) && isset($fl->branches[$onb])): ?>
- <em>(<?php echo _("Tracking Branch") ?> <strong><?php echo $fl->branches[$onb] ?></strong>)</em>
+ <?php if (!empty($onb)): ?>
+ <em>(<?php echo _("Tracking Branch") ?> <strong><?php echo $onb ?></strong>)</em>
<?php endif; ?>
</td>
<?php if (!empty($extraLink)): ?>
<?php endif ?>
<a href="<?php echo Chora::url('diff', $where, array('r1' => 0, 'r2' => $rev)) ?>" class="sdiff" title="<?php echo _("Show changes to the selected revision") ?>" onclick="Chora_RevLog.sdiff(this);"><?php echo Horde::img('diff.png') ?></a>
</td>
- <td><a href="<?php echo $textUrl ?>" title="<?php echo htmlspecialchars($rev) ?>"><?php echo htmlspecialchars($rev_ob->abbrev($rev)) . '</a>'; if ($branchName) echo ' <span class="branch">' . Horde::link(Chora::url('', $where, array('onb' => $branchRev))) . htmlspecialchars($branchName) . '</a></span>'; if (!empty($lg->lines)) echo ' <small>(' . sprintf('%s lines', $lg->lines) . ')</small>'; ?></td>
+ <td><a href="<?php echo $textUrl ?>" title="<?php echo htmlspecialchars($rev) ?>"><?php echo htmlspecialchars($rev_ob->abbrev($rev)) ?></a>
+<?php foreach (array_diff($branch_info, array($onb)) as $val): ?>
+ <span class="branch"><?php echo Horde::link(Chora::url('', $where, array('onb' => $val))) . htmlspecialchars($val) ?></a></span>
+<?php endforeach; ?>
+<?php if (!empty($lg->lines)): ?>
+ <small>(<?php printf('%s lines', $lg->lines) ?>)</small>
+<?php endif; ?>
+</td>
<td class="ago" sortval="<?php echo (int)$lg->date ?>"><a title="<?php echo $readableDate ?>"><?php echo $commitDate ?></a></td>
<td class="author"><?php echo $author ?></td>
<td class="log">
-<?php
-echo '<p class="message">' . $logMessage . '</p>';
-if ($tags) echo '<p class="tags">' . _("Tags") . ': ' . implode(', ', $tags) . '</p>';
-?>
+ <p class="message"><?php echo $logMessage ?></p>
+<?php if ($tags): ?>
+ <p class="tags"><?php echo _("Tags") . ': ' . implode(', ', $tags) ?></p>
+<?php endif; ?>
</td>
</tr>
}
/**
- * Does this driver support the given feature
+ * Does this driver support the given feature?
*
* @return boolean True if driver supports the given feature.
*/
- public function supportsFeature($feature)
+ public function hasFeature($feature)
{
switch ($feature) {
case 'branches':
public $rep;
public $dir;
public $name;
- public $logs;
- public $revs;
+ public $logs = array();
+ public $revs = array();
public $head;
public $quicklog;
- public $symrev;
- public $revsym;
- public $branches;
+ public $symrev = array();
+ public $revsym = array();
+ public $branches = array();
public $revob;
/**
/**
* Constructor.
*/
- public function __construct($rep, $fl)
+ public function __construct($fl)
{
- $this->rep = $rep;
$this->file = $fl;
+ $this->rep = $fl->rep;
}
public function queryDate()
* accordingly, and performs a lookup on the file object to
* return the symbolic name(s) of that branch in the tree.
*
- * @return hash of symbolic names => branch numbers
+ * @return array Hash of symbolic names => branch numbers.
*/
public function querySymbolicBranches()
{
$symBranches = array();
foreach ($this->branches as $branch) {
- $parts = explode('.', $branch);
- $last = array_pop($parts);
- $parts[] = '0';
- $parts[] = $last;
- $rev = implode('.', $parts);
- if (isset($this->file->branches[$branch])) {
- $symBranches[$this->file->branches[$branch]] = $branch;
+ $key = array_search($branch, $this->file->branches);
+ if ($key !== false) {
+ $symBranches[$key] = $branch;
}
}
$this->filename = $fl;
$this->cache = $cache;
$this->quicklog = $quicklog;
- $this->logs = $this->revs = $this->branches = array();
}
public function &getFileObject()
case 'init':
if (!strncmp('head: ', $line, 6)) {
$this->head = substr($line, 6);
- $this->branches[$this->head] = 'HEAD';
+ $this->branches['HEAD'] = $this->head;
} elseif (!strncmp('branch:', $line, 7)) {
$state = 'rev';
}
// Check to see if this is a branch
if (preg_match('/^(\d+(\.\d+)+)\.0\.(\d+)$/', $regs[2])) {
$branchRev = $this->toBranch($regs[2]);
- if (!isset($this->branches[$branchRev])) {
- $this->branches[$branchRev] = $regs[1];
- }
+ $this->branches[$regs[1]] = $branchRev;
} else {
$symrev[$regs[1]] = $regs[2];
if (empty($revsym[$regs[2]])) {
} elseif (count($accum)) {
// Spawn a new Horde_Vcs_Log object and add it to the logs
// hash.
- $log = new Horde_Vcs_Log_Cvs($this->rep, $this->filename);
+ $log = new Horde_Vcs_Log_Cvs($this);
$err = $log->processLog($accum);
// TODO: error checks - avsm
$this->logs[$log->queryRevision()] = $log;
case 'branches':
/* If we find a branch tag, process and pop it,
otherwise leave input stream untouched */
- if (!empty($raw) && preg_match("/^branches:\s+(.*)/", $raw[0], $br)) {
+ if (!empty($raw) &&
+ preg_match("/^branches:\s+(.*)/", $raw[0], $br)) {
/* Get the list of branches from the string, and
* push valid revisions into the branches array */
$brs = preg_split('/;\s*/', $br[1]);
foreach ($brs as $brpoint) {
if ($this->rep->isValidRevision($brpoint)) {
+ // TODO: Need branchname
$this->branches[] = $brpoint;
}
}
*
* @var boolean
*/
- /* @TODO */
- protected $_branches = false;
+ protected $_branches = true;
/**
* Constructor.
$command = $this->_rep->getCommand() . ' blame -p ' . $rev . ' -- ' . escapeshellarg($this->_file->queryModulePath()) . ' 2>&1';
$pipe = popen($command, 'r');
if (!$pipe) {
- return PEAR::raiseError('Failed to execute git annotate: ' . $command);
+ throw new Horde_Vcs_Exception('Failed to execute git annotate: ' . $command);
}
$curr_rev = null;
$file_ob = $rep->getFileObject($file);
- return ($pipe = popen($rep->getCommand() . ' cat-file blob ' . $file_ob->getHashForRevision($rev) . ' 2>&1', VC_WINDOWS ? 'rb' : 'r'))
- ? $pipe
- : PEAR::raiseError('Couldn\'t perform checkout of the requested file');
+ if ($pipe = popen($rep->getCommand() . ' cat-file blob ' . $file_ob->getHashForRevision($rev) . ' 2>&1', VC_WINDOWS ? 'rb' : 'r')) {
+ return $pipe;
+ }
+
+ throw new Horde_Vcs_Exception('Couldn\'t perform checkout of the requested file');
}
}
$dir = popen($cmd, 'r');
if (!$dir) {
- return PEAR::raiseError('Failed to execute git ls-tree: ' . $cmd);
+ throw new Horde_Vcs_Exception('Failed to execute git ls-tree: ' . $cmd);
}
// Create two arrays - one of all the files, and the other of
$this->dir = dirname($fl);
$this->quicklog = $quicklog;
$this->cache = $cache;
-
- $this->logs = $this->revs = $this->revsym = $this->symrev = $this->branches = array();
}
+ /**
+ * TODO
+ */
public function getFileObject()
{
$this->getBrowseInfo();
/**
* Get the hash name for this file at a specific revision.
*
- * @param string $rev
+ * @param string $rev TODO
*
- * @return string Commit hash
+ * @return string Commit hash.
*/
public function getHashForRevision($rev)
{
* Returns name of the current file without the repository
* extensions (usually ,v)
*
- * @return Filename without repository extension
+ * @return string Filename without repository extension
*/
function queryName()
{
/**
* Populate the object with information about the revisions logs
* and dates of the file.
- *
- * @return mixed True on success, PEAR_Error on error.
*/
function getBrowseInfo()
{
// Get the list of revisions that touch this path
- $cmd = $this->rep->getCommand() . ' rev-list ' . escapeshellarg($this->_branch) . ' -- ' . escapeshellarg($this->fullname) . ' 2>&1';
+ // 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);
$this->revs = explode("\n", trim($revisions));
foreach ($this->revs as $rev) {
- $this->logs[$rev] = Horde_Vcs_Log_Git::factory($this->rep, $this, $rev);
+ $this->logs[$rev] = Horde_Vcs_Log_Git::factory($this, $rev);
if ($this->quicklog) {
break;
}
}
// Add branch information
- $cmd = $this->rep->getCommand() . ' branch -l';
+ $cmd = $this->rep->getCommand() . ' show-ref --heads';
$branch_list = shell_exec($cmd);
if (empty($branch_list)) {
throw new Horde_Vcs_Exception('No branches found');
}
- $i = 0;
foreach (explode("\n", trim($branch_list)) as $val) {
- $this->branches[++$i] = ltrim($val, '* ');
+ $line = explode(' ', trim($val), 2);
+ $this->branches[substr($line[1], strrpos($line[1], '/') + 1)] = $line[0];
}
}
public $err;
public $files = array();
- public static function factory($rep, $file, $rev)
+ public static function factory($file, $rev)
{
/* The version of the cached data. Increment this whenever the
* internal storage format changes, such that we must
* invalidate prior cached data. */
$cacheVersion = 1;
- $cacheId = $rep->sourceroot() . '_r' . $rev . '_v' . $cacheVersion;
+ $cacheId = $file->rep->sourceroot() . '_r' . $rev . '_v' . $cacheVersion;
/* @TODO: No caching during dev */
if (0 &&
- $rep->cache &&
+ $file->rep->cache &&
// Individual revisions can be cached forever
- $rep->cache->exists($cacheId, 0)) {
- $logOb = unserialize($rep->cache->get($cacheId, 0));
- $logOb->setRepository($rep);
+ $file->rep->cache->exists($cacheId, 0)) {
+ $logOb = unserialize($file->rep->cache->get($cacheId, 0));
+ $logOb->setRepository($file->rep);
} else {
- $logOb = new Horde_Vcs_Log_Git($rep, $file, $rev);
+ $logOb = new Horde_Vcs_Log_Git($file, $rev);
- if ($rep->cache) {
- $rep->cache->set($cacheId, serialize($logOb));
+ if ($file->rep->cache) {
+ $file->rep->cache->set($cacheId, serialize($logOb));
}
}
/**
* Constructor.
*/
- public function __construct($rep, $fl, $rev)
+ public function __construct($fl, $rev)
{
- parent::__construct($rep, $fl);
+ parent::__construct($fl);
$this->rev = $rev;
$value = substr($value, 1, -1);
foreach (explode(',', $value) as $val) {
$val = trim($val);
- if (($pos = strrpos($val, '/')) !== false) {
- $this->tags[] = substr($val, $pos + 1);
+ if (strpos($val, 'refs/tags/') === 0) {
+ $this->tags[] = substr($val, 10);
}
}
if (!empty($this->tags)) {
$this->filename = $fl;
$this->quicklog = $quicklog;
$this->cache = $cache;
- $this->logs = $this->revs = $this->revsym = $this->symrev = $this->branches = array();
}
public function getFileObject()