From 9cee6c185ef30a313de9a1c0f320da3db362593f Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Tue, 16 Jun 2009 23:57:44 -0600 Subject: [PATCH] Add diffstat information. Diffstat info added to single patchset, diff, and browsefile screens. Currently, only git supports. CVS uses a different way to generate this info (see queryChangedLines()), but should eventually be changed to the same mechanism - this diff information should not live directly in the log object, but rather in the file objects inside of the master log object. --- chora/browsefile.php | 10 ++++++++ chora/diff.php | 9 +++++-- chora/patchsets.php | 5 ++++ chora/templates/diff/hr/header.inc | 1 + chora/templates/log/rev.inc | 7 +++-- chora/templates/patchsets/ps_single.inc | 2 +- chora/themes/screen.css | 8 ++++++ framework/Vcs/lib/Horde/Vcs.php | 15 ++++++++++- framework/Vcs/lib/Horde/Vcs/Git.php | 45 ++++++++++++++++++++------------- 9 files changed, 78 insertions(+), 24 deletions(-) diff --git a/chora/browsefile.php b/chora/browsefile.php index 0c1854f09..dd35aa1dd 100644 --- a/chora/browsefile.php +++ b/chora/browsefile.php @@ -61,6 +61,16 @@ while (list(,$lg) = each($logs)) { $rev = $lg->queryRevision(); $branch_info = $lg->queryBranch(); + $added = $deleted = null; + $fileinfo = $lg->queryFiles($where); + if ($fileinfo && isset($fileinfo['added'])) { + $added = $fileinfo['added']; + $deleted = $fileinfo['deleted']; + } + + // TODO: Remove in favor of getting info from queryFiles() + $changedlines = $lg->queryChangedLines(); + $textUrl = Chora::url('co', $where, array('r' => $rev)); $commitDate = Chora::formatDate($lg->queryDate()); $readableDate = Chora::readableTime($lg->queryDate(), true); diff --git a/chora/diff.php b/chora/diff.php index 12fb38a02..8f02517b0 100644 --- a/chora/diff.php +++ b/chora/diff.php @@ -61,14 +61,19 @@ $log_messages = array(); foreach ($VC->getRevisionRange($fl, $r1, $r2) as $val) { $clog = $fl->queryLogs($val); if (!is_null($clog)) { - $log_messages[] = array( + $fileinfo = $clog->queryFiles($where); + $stats = ($fileinfo && isset($fileinfo['added'])) + ? array('added' => $fileinfo['added'], 'deleted' => $fileinfo['deleted']) + : array(); + + $log_messages[] = array_merge(array( 'rev' => $val, 'msg' => Chora::formatLogMessage($clog->queryLog()), 'author' => Chora::showAuthorName($clog->queryAuthor(), true), 'branchinfo' => $clog->queryBranch(), 'date' => Chora::formatDate($clog->queryDate()), 'tags' => Chora::getTags($clog, $where), - ); + ), $stats); } } diff --git a/chora/patchsets.php b/chora/patchsets.php index c454ebf43..17dcde2b3 100644 --- a/chora/patchsets.php +++ b/chora/patchsets.php @@ -89,6 +89,11 @@ while (list($id, $patchset) = each($patchsets)) { $file['to'] = Horde::link(Chora::url('co', $member['file'], array('r' => $member['to'])), $member['to']) . htmlspecialchars($VC->abbrev($member['to'])) . ''; } + if (isset($member['added'])) { + $file['added'] = $member['added']; + $file['deleted'] = $member['deleted']; + } + $files[] = $file; } diff --git a/chora/templates/diff/hr/header.inc b/chora/templates/diff/hr/header.inc index 244cbe0d2..ed51a374a 100644 --- a/chora/templates/diff/hr/header.inc +++ b/chora/templates/diff/hr/header.inc @@ -50,6 +50,7 @@
  • +
  • + , -
  • abbrev($val['rev'])) ?>:
    diff --git a/chora/templates/log/rev.inc b/chora/templates/log/rev.inc index cdf066d68..701949193 100644 --- a/chora/templates/log/rev.inc +++ b/chora/templates/log/rev.inc @@ -9,8 +9,11 @@ $val))) . htmlspecialchars($val) ?> -lines)): ?> - (lines) ?>) + + () + + + (+, - ) diff --git a/chora/templates/patchsets/ps_single.inc b/chora/templates/patchsets/ps_single.inc index c8eacbe66..4f0cab21f 100644 --- a/chora/templates/patchsets/ps_single.inc +++ b/chora/templates/patchsets/ps_single.inc @@ -25,6 +25,6 @@ diff --git a/chora/themes/screen.css b/chora/themes/screen.css index b060a3204..f2248d3b3 100644 --- a/chora/themes/screen.css +++ b/chora/themes/screen.css @@ -170,6 +170,14 @@ ul.singlepsfiles li { padding-bottom: 4px; } +/* Diff stat information. */ +.diffadd { + color: blue; +} +.diffdel { + color: red; +} + /* Checkout. */ div.checkout { padding: 3px; diff --git a/framework/Vcs/lib/Horde/Vcs.php b/framework/Vcs/lib/Horde/Vcs.php index 343b05c89..ab50b384f 100644 --- a/framework/Vcs/lib/Horde/Vcs.php +++ b/framework/Vcs/lib/Horde/Vcs.php @@ -1029,7 +1029,9 @@ abstract class Horde_Vcs_File */ public function queryLogs($rev = null) { - return is_null($rev) ? $this->_logs : (isset($this->_logs[$rev]) ? $this->_logs[$rev] : null); + return is_null($rev) + ? $this->_logs + : (isset($this->_logs[$rev]) ? $this->_logs[$rev] : null); } /** @@ -1059,6 +1061,7 @@ abstract class Horde_Vcs_Log { protected $_rep; protected $_file; + protected $_files; protected $_rev; protected $_author; protected $_tags = array(); @@ -1163,6 +1166,16 @@ abstract class Horde_Vcs_Log return $symBranches; } + /** + * TODO + */ + public function queryFiles($file = null) + { + return is_null($file) + ? $this->_files + : (isset($this->_files[$file]) ? $this->_files[$file] : null); + } + } /** diff --git a/framework/Vcs/lib/Horde/Vcs/Git.php b/framework/Vcs/lib/Horde/Vcs/Git.php index d288f55e9..ca3de1f68 100644 --- a/framework/Vcs/lib/Horde/Vcs/Git.php +++ b/framework/Vcs/lib/Horde/Vcs/Git.php @@ -625,11 +625,6 @@ class Horde_Vcs_Log_Git extends Horde_Vcs_Log protected $_parent = null; /** - * @var array - */ - protected $_files = array(); - - /** * Constructor. * * @throws Horde_Vcs_Exception @@ -638,8 +633,21 @@ class Horde_Vcs_Log_Git extends Horde_Vcs_Log { parent::__construct($rep, $fl, $rev); + /* Get diff statistics. */ + $stats = array(); + $cmd = $rep->getCommand() . ' diff-tree --numstat ' . escapeshellarg($rev); + exec($cmd, $output); + + reset($output); + // Skip the first entry (it is the revision number) + next($output); + while (list(,$v) = each($output)) { + $tmp = explode("\t", $v); + $stats[$tmp[2]] = array_slice($tmp, 0, 2); + } + // @TODO use Commit, CommitDate, and Merge properties - $cmd = $rep->getCommand() . ' whatchanged --no-color --pretty=format:"Rev:%H%nParents:%P%nAuthor:%an <%ae>%nAuthorDate:%at%nRefs:%d%n%n%s%n%b" --no-abbrev -n 1 ' . $rev; + $cmd = $rep->getCommand() . ' whatchanged --no-color --pretty=format:"Rev:%H%nParents:%P%nAuthor:%an <%ae>%nAuthorDate:%at%nRefs:%d%n%n%s%n%b" --no-abbrev -n 1 ' . escapeshellarg($rev); $pipe = popen($cmd, 'r'); if (!is_resource($pipe)) { throw new Horde_Vcs_Exception('Unable to run ' . $cmd . ': ' . error_get_last()); @@ -713,7 +721,12 @@ class Horde_Vcs_Log_Git extends Horde_Vcs_Log // http://www.kernel.org/pub/software/scm/git/docs/git-diff-tree.html while ($line) { preg_match('/:(\d+) (\d+) (\w+) (\w+) (.+)\t(.+)(\t(.+))?/', $line, $matches); - $this->_files[$matches[6]] = array( + + $statinfo = isset($stats[$matches[6]]) + ? array('added' => $stats[$matches[6]][0], 'deleted' => $stats[$matches[6]][1]) + : array(); + + $this->_files[$matches[6]] = array_merge(array( 'srcMode' => $matches[1], 'dstMode' => $matches[2], 'srcSha1' => $matches[3], @@ -721,7 +734,7 @@ class Horde_Vcs_Log_Git extends Horde_Vcs_Log 'status' => $matches[5], 'srcPath' => $matches[6], 'dstPath' => isset($matches[7]) ? $matches[7] : '' - ); + ), $statinfo); $line = fgets($pipe); } @@ -748,14 +761,6 @@ class Horde_Vcs_Log_Git extends Horde_Vcs_Log /** * TODO */ - public function queryFiles() - { - return $this->_files; - } - - /** - * TODO - */ public function queryParent() { return $this->_parent; @@ -831,12 +836,16 @@ class Horde_Vcs_Patchset_Git extends Horde_Vcs_Patchset $from = $log->queryParent(); } - $this->_patchsets[$rev]['members'][] = array( + $statinfo = isset($file['added']) + ? array('added' => $file['added'], 'deleted' => $file['deleted']) + : array(); + + $this->_patchsets[$rev]['members'][] = array_merge(array( 'file' => $file['srcPath'], 'from' => $from, 'status' => $status, 'to' => $to, - ); + ), $statinfo); } } } -- 2.11.0