From d03bcfc0e90a1a4ef58e8051f4a0a29db68134a1 Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Tue, 10 Apr 2007 03:50:35 +0000 Subject: [PATCH] - In Revision::getRevisionInfo(), we want to use the verbose option for our call to log so we can get file changes - Added ConstructFileChanges() - Adding includes/class_diff.php to parse diffs... I want to rewrite this because it's fugly code - Rudimentary diff now works --- diff.php | 87 +++----- includes/{svnlib.php => class_diff.php} | 262 ++++-------------------- includes/class_revision.php | 10 +- includes/functions.php | 55 +++++ includes/init.php | 2 - includes/svncommon.php | 121 ----------- templates/default/diff.tpl | 12 +- 7 files changed, 137 insertions(+), 412 deletions(-) rename includes/{svnlib.php => class_diff.php} (53%) delete mode 100644 includes/svncommon.php diff --git a/diff.php b/diff.php index 3390481..1341da4 100644 --- a/diff.php +++ b/diff.php @@ -28,61 +28,35 @@ $fetchtemplates = array( 'property' ); -require_once('./global.php'); - -$navbar = $controller->construct_breadcrumb(); +define('SVN', '$Id$'); -// ################################################################### +require_once('./global.php'); +require_once('./includes/class_diff.php'); -$link['log'] = $controller->href_compound('log.php'); +$navbar = ConstructNavbar(); // ################################################################### -if (isset($viewsvn->in['rev'])) -{ - $high = Paths::fetch_rev_num(false); -} -else -{ - $revs = Paths::fetch_rev_num(true); - $high = $revs['high']; - $low = $revs['low']; -} - -if ($high == 'HEAD') -{ - $high = $controller->cachev->fetch_head_revision(); -} - -if ($low == 0) -{ - $low = $controller->cachev->fetch_prev_revision($high); - $low = $low['revision']; -} +$link['log'] = ConstructLink('log', $input->in['repos'], $input->in['path'], $input->in['rev']); // ################################################################### -$show['fullchangeset'] = (Paths::is_root_path($controller->path) ? false : true); +$show['fullchangeset'] = ($input->in['path'] == '' OR $input->in['path'] == '/'); if ($show['fullchangeset']) { - $link['changeset'] = $controller->href_struct('diff.php' . Paths::fetch_rev_str(true, $high, $low), ''); + $link['changeset'] = ConstructLink('diff', $input->in['repos'], null, $input->in['rev']); } -$log = $controller->cachev->fetch_revision($high); +$revision = new Revision($input->in['repos'], $input->in['rev'], $input->in['path']); +$revision->getRevisionInfo(); -$log['message_clean'] = SVNCommon::format_log_message($log['message']); -$log['date'] = SVNCommon::format_date_string($log['dateline']); - -$files = SVNCommon::construct_file_changes($log['files'], $controller->repos, $high); +$files = ConstructFileChanges($revision->files, $input->in['repos'], $revision->revision); // ################################################################### -$diff = new SVNDiff($controller, $low, $high); - -$isdir = (bool)$controller->cachev->isdir(); +$diff = new Diff($lib->run('diff -c' . $revision->revision . ' ' . $lib->arg($repos->fetchPath($input->in['repos']) . '/' . $input->in['path']))); $changes = ''; - foreach ($diff->fetch() AS $filename => $file) { $hunktpl = ''; @@ -106,8 +80,8 @@ foreach ($diff->fetch() AS $filename => $file) if ($key == 'hunk' AND isset($line['old'])) { $filepath = ($isdir ? $controller->path . $filename : $controller->path); - $rlow = $controller->href_struct('view.php' . Paths::fetch_rev_str(false, $low), $filepath); - $rhigh = $controller->href_struct('view.php' . Paths::fetch_rev_str(false, $high), $filepath); + // $rlow = $controller->href_struct('view.php' . Paths::fetch_rev_str(false, $low), $filepath); + // $rhigh = $controller->href_struct('view.php' . Paths::fetch_rev_str(false, $high), $filepath); $show['hunk'] = true; } else @@ -125,7 +99,7 @@ foreach ($diff->fetch() AS $filename => $file) $class = 'diff_norm'; } - $line['line_clean'] = SVNCommon::format($line['line']); + $line['line_clean'] = FormatCode($line['line']); } eval('$lines .= "' . $template->fetch('diff_line') . '";'); @@ -133,24 +107,27 @@ foreach ($diff->fetch() AS $filename => $file) eval('$hunktpl .= "' . $template->fetch('diff_hunk') . '";'); } - foreach ($props AS $name => $values) + if (is_array($props)) { - // modified - if (isset($values['add']) AND isset($values['del'])) - { - $data = sprintf($lang->string('Property %1$s changed from %2$s to %3$s'), $name, $values['del'], $values['add']); - } - // added - else if (isset($values['add'])) - { - $data = sprintf($lang->string('Property %1$s set to %2$s'), $name, $values['add']); - } - // removed - else if (isset($values['del'])) + foreach ($props AS $name => $values) { - $data = sprintf($lang->string('Property %1$s deleted'), $name); + // modified + if (isset($values['add']) AND isset($values['del'])) + { + $data = sprintf(_('Property %1$s changed from %2$s to %3$s'), $name, $values['del'], $values['add']); + } + // added + else if (isset($values['add'])) + { + $data = sprintf(_('Property %1$s set to %2$s'), $name, $values['add']); + } + // removed + else if (isset($values['del'])) + { + $data = sprintf(_('Property %1$s deleted'), $name); + } + eval('$proplist .= "' . $template->fetch('property') . '";'); } - eval('$proplist .= "' . $template->fetch('property') . '";'); } eval('$changes .= "' . $template->fetch('diff_file') . '";'); diff --git a/includes/svnlib.php b/includes/class_diff.php similarity index 53% rename from includes/svnlib.php rename to includes/class_diff.php index f2ab77f..c8e7893 100644 --- a/includes/svnlib.php +++ b/includes/class_diff.php @@ -2,7 +2,7 @@ /*=====================================================================*\ || ################################################################### || # ViewSVN [#]version[#] -|| # Copyright ©2002-[#]year[#] Iris Studios, Inc. +|| # Copyright ©2002-[#]year[#] Blue Static || # || # This program is free software; you can redistribute it and/or modify || # it under the terms of the GNU General Public License as published by @@ -20,242 +20,50 @@ \*=====================================================================*/ /** -* Command line library and SVN-PHP bridge extension +* Diff * -* @package ViewSVN -*/ - -/** -* This class acts as the bridge between the command line Xquery class -* and the various display files. It handles preparation of Xquery -* code. +* This class parses a diff file from a unified diff file and turns it +* into a HTML-prettied output * -* @package ViewSVN -* @version $Id$ -*/ -class SVNLib -{ - /** - * Path to the SVN binary - * @var string - * @access private - */ - var $svnpath; - - /** - * Controller - * @var object - * @access private - */ - var $controller; - - // ################################################################### - /** - * Constructor: validate SVN path - * - * @param object Controller - */ - function SVNLib(&$controller) - { - $this->controller =& $controller; - - $this->svnpath =& $this->controller->xquery->cmd($this->controller->registry->svnpath); - - $access = $this->controller->xquery->exec($this->svnpath . ' --version'); - - if (!$access) - { - $this->controller->registry->trigger->error($this->controller->registry->lang->string('The SVN binary could not be located')); - } - - if (!preg_match('#^svn, version (.*?)\)$#i', trim($access[0]))) - { - $this->controller->registry->trigger->error($this->controller->registry->lang->string('The SVN binary does not appear to be valid (it failed our tests)')); - } - } - - // ################################################################### - /** - * Executes the SVN binary - * - * @access private - * - * @param string Command - * - * @return array Output - */ - function svn($command) - { - $output = $this->controller->xquery->exec($this->svnpath . ' ' . $command . ' 2>&1'); - - $temp = implode("\n", $output); - if (strpos($temp, '(apr' . '_err=') !== false) - { - $this->controller->registry->trigger->error(nl2br($temp)); - } - return $output; - } - - // ################################################################### - /** - * This function is used to prepare a common command. It sends the - * specified command along with the repository path and the current - * node. The revision is either fectched from the argument list or - * from the node, too. - * - * @access public - * - * @param string SVN command - * @param bool Alternate revision - * - * @return array Lines of output - */ - function command($command, $rev = false) - { - global $viewsvn; - - $revision = ($rev !== false ? $rev : SVNCommon::rev($this->controller->revnum)); - - return $this->svn($command . ' ' . $this->controller->repospath . $this->controller->path . ($revision !== null ? '@' . $revision : '')); - } - - // ################################################################### - /** - * A library complicator function that handles the diff command because - * the standard command() system does not work with more complex args. - * - * @access public - * - * @param integer Lower revision - * @param integer Higher revision - * - * @return array Lines of diff output - */ - function diff($lorev, $hirev) - { - global $viewsvn; - - $hirev = SVNCommon::rev($hirev); - $lorev = SVNCommon::rev($lorev); - if ($lorev == 'HEAD') - { - $lorev = 1; - } - - if (is_integer($hirev) AND is_integer($lorev)) - { - if ($lorev > $hirev) - { - $lorev = $hirev - 1; - } - if ($lorev == $hirev) - { - $lorev = 0; - } - } - - return $this->svn('diff -r' . $lorev . ':' . $hirev . ' ' . $this->controller->repospath . $this->controller->path); - } - - // ################################################################### - /** - * A library complicator function to create log output. This is needed - * because command() doesn't handle ranged revisions. - * - * @access public - * - * @param string Repository - * @param string Path - * @param integer Lower revision - * @param integer Higher revision - * - * @return array Lines of log output - */ - function log($lorev, $hirev) - { - global $viewsvn; - - $hirev = $this->rev($hirev); - $lorev = $this->rev($hirev); - if ($lorev == 'HEAD') - { - $lorev = 0; - } - - if (is_integer($hirev) AND is_integer($lorev)) - { - if ($lorev > $hirev) - { - $lorev = $hirev - 1; - } - if ($lorev == $hirev) - { - $lorev = 0; - } - } - - $repospath = $viewsvn->repos->fetch_path($repos, false); - - return $this->svn('log -v -r' . $hirev . ':' . $lorev . ' ' . $repospath . $path); - } -} - -/** -* Diff system; constructs a diff array that is ready for output +* @author Blue Static +* @copyright Copyright (c)2002 - [#]year[#], Blue Static +* @version $Revision$ +* @package ViewSVN * -* @package ViewSVN -* @version $Id$ */ -class SVNDiff +class Diff { /** - * Array of diff information - * @var array - * @access private + * Raw unified diff text + * @var string */ - var $diff = array(); + private $raw; /** - * Raw "svn diff" output - * @var array - * @access private + * The current index (file) + * @var string */ - var $rawoutput; + private $index; // ################################################################### /** - * Constructor: create and store diff data + * Constructor * - * @param object Controller - * @param integer Lower revision - * @param integer Higher revision + * @param string Raw unified diff output */ - function SVNDiff(&$controller, $lorev, $hirev) + public function __construct($raw) { - $this->rawoutput = $controller->library->diff($lorev, $hirev); - $this->process(); + $this->raw = $raw; } // ################################################################### /** - * Returns diffs for display - * - * @access public + * This function initiates the parsing process and returns the output + * in hunks, line-by-line * - * @return array Diff data + * @return array Array of outputted hunked information */ - function fetch() - { - return $this->diff; - } - - // ################################################################### - /** - * Processes and prepares diff data - * - * @access private - */ - function process() + public function fetch() { global $viewsvn; @@ -265,7 +73,7 @@ class SVNDiff $delstack = array(); - foreach ($this->rawoutput AS $line) + foreach ($this->raw AS $line) { if (preg_match('#^@@ \-([0-9]*),([0-9]*) \+([0-9]*),([0-9]*) @@$#', $line, $bits)) { @@ -318,12 +126,12 @@ class SVNDiff { $lastline = array_shift($delstack); - if ($delta = @$this->fetch_diff_extent($lastline['line'], $content)) + if ($delta = @$this->_fetchDiffExtent($lastline['line'], $content)) { if (strlen($lastline['line']) > ($delta['start'] - $delta['end'])) { $end = strlen($lastline['line']) + $delta['end']; - $viewsvn->debug("RM delta- = " . $end); + BSRegister::Debug("RM delta- = " . $end); $change = '{@-' . '-}' . substr($lastline['line'], $delta['start'], $end - $delta['start']) . '{/@-' . '-}'; $this->diff["$index"]["$chunk"]["$lastline[INDEX]"]['line'] = substr($lastline['line'], 0, $delta['start']) . $change . substr($lastline['line'], $end); } @@ -331,7 +139,7 @@ class SVNDiff if (strlen($content) > $delta['start'] - $delta['end']) { $end = strlen($content) + $delta['end']; - $viewsvn->debug("MK delta+ = " . $end); + BSRegister::Debug("MK delta+ = " . $end); $change = '{@+' . '+}' . substr($content, $delta['start'], $end - $delta['start']) . '{/@+' . '+}'; $content = substr($content, 0, $delta['start']) . $change . substr($content, $end); } @@ -375,14 +183,14 @@ class SVNDiff { if (preg_match('#^__*_$#', trim($line))) { - $viewsvn->debug("skipping: $line"); + BSRegister::Debug("skipping: $line"); continue; } if (preg_match('#Name: (.*?)$#', $line, $matches)) { $curprop = $matches[1]; - $viewsvn->debug("prop: $curprop"); + BSRegister::Debug("prop: $curprop"); continue; } else @@ -415,27 +223,27 @@ class SVNDiff $delstack = array(); } } + + return $this->diff; } // ################################################################### /** * Returns the amount of change that occured between two lines * - * @access private - * * @param string Old line * @param string New line * * @return array Difference of positions */ - function fetch_diff_extent($old, $new) + private function _fetchDiffExtent($old, $new) { global $viewsvn; $start = 0; $min = min(strlen($old), strlen($new)); - $viewsvn->debug("min1 = $min"); + BSRegister::Debug("min1 = $min"); while ($start < $min AND $old["$start"] == $new["$start"]) { @@ -445,9 +253,9 @@ class SVNDiff $end = -1; $min = $min - $start; - $viewsvn->debug("min2 = $min"); + BSRegister::Debug("min2 = $min"); - $viewsvn->debug("checking: " . $old[ strlen($old) + $end ] . ' == ' . $new[ strlen($new) + $end ]); + BSRegister::Debug("checking: " . $old[ strlen($old) + $end ] . ' == ' . $new[ strlen($new) + $end ]); while (-$end <= $min AND $old[ strlen($old) + $end ] == $new[ strlen($new) + $end ]) { diff --git a/includes/class_revision.php b/includes/class_revision.php index bec4459..4d29915 100644 --- a/includes/class_revision.php +++ b/includes/class_revision.php @@ -80,6 +80,12 @@ class Revision */ public $datetime; + /** + * Files changed by the revision + * @var array + */ + public $files = array(); + // ################################################################### /** * Creates a new revision for a given repository and revision @@ -134,11 +140,13 @@ class Revision */ public function getRevisionInfo() { - $xml = BSXml::Parse(BSRegister::Get('lib')->run('log --xml -r' . $this->revision . ' ' . BSRegister::Get('lib')->arg($this->path), true)); + $xml = BSXml::Parse(BSRegister::Get('lib')->run('log --xml -v -r' . $this->revision . ' ' . BSRegister::Get('lib')->arg($this->path), true)); $this->message = FormatLogMessage($xml['log']['logentry']['msg']['value']); $this->messasgeClean = $xml['log']['logentry']['msg']['value']; $this->datetime = FormatSvnDate($xml['log']['logentry']['date']['value']); $this->author = $xml['log']['logentry']['author']['value']; + $this->files = $xml['log']['logentry']['paths']['path']; + BSXml::UnifyNode($this->files); } // ################################################################### diff --git a/includes/functions.php b/includes/functions.php index cea2366..e7d8d7c 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -226,6 +226,61 @@ function _FormatSpaces($thestring) return $thestring; } +// ################################################################### +/** +* Takes in an array of files with a path and an action and constructs +* the HTML block describing them +* +* @param array List of file changes +* @param string The repository +* @param integer Current revision +* +* @return string Processed HTML +*/ +function ConstructFileChanges($changes, $repos, $revision) +{ + $files = ''; + + foreach ($changes AS $file) + { + switch ($file['action']) + { + case 'A': + $class = 'file_add'; + $tooltip = _('Added'); + break; + case 'D': + $class = 'file_delete'; + $tooltip = _('Deleted'); + break; + case 'M': + $class = 'file_modify'; + $tooltip = _('Modified'); + break; + case 'R': + $class = 'file_replace'; + $tooltip = _('Replaced'); + break; + } + + $show['from'] = (bool)$file['from']; + + if ($file['from']) + { + $class = 'file_move'; + $tooltip = _('Moved/Copied'); + preg_match('#(.*):([0-9]+)#', $file['from'], $matches); + $link['from'] = ConstructLink('view', $repos, $matches[1], $revision); + } + + $link['file'] = ConstructLink('view', $repos, $file['value'], $revision); + + eval('$files .= "' . BSRegister::Get('template')->fetch('file_change') . '";'); + } + + return $files; +} + /*=====================================================================*\ || ################################################################### || # $HeadURL$ diff --git a/includes/init.php b/includes/init.php index e6eecff..ba393ac 100644 --- a/includes/init.php +++ b/includes/init.php @@ -59,8 +59,6 @@ $template->setExtension('tpl'); // load options BSRegister::Register('svnpath', $conf['paths']['svn']); -require_once('./includes/svncommon.php'); - // ################################################################### // imaginary reporter require_once('./includes/imaginary.php'); diff --git a/includes/svncommon.php b/includes/svncommon.php deleted file mode 100644 index 8a128c2..0000000 --- a/includes/svncommon.php +++ /dev/null @@ -1,121 +0,0 @@ -lang->string('Added'); - break; - case 'D': - $class = 'file_delete'; - $tooltip = $viewsvn->lang->string('Deleted'); - break; - case 'M': - $class = 'file_modify'; - $tooltip = $viewsvn->lang->string('Modified'); - break; - case 'R': - $class = 'file_replace'; - $tooltip = $viewsvn->lang->string('Replaced'); - break; - } - - $show['from'] = (bool)$file['from']; - - if ($file['from']) - { - $class = 'file_move'; - $tooltip = 'Moved/Copied'; - preg_match('#(.*):([0-9]+)#', $file['from'], $matches); - $link['from'] = $viewsvn->path . '/view.php/' . $repos . '/' . $matches[1] . Paths::fetch_rev_str(false, $matches[2]); - } - - $link['file'] = $viewsvn->path . '/view.php/' . $repos . $file['value'] . Paths::fetch_rev_str(false, $revision); - - eval('$files .= "' . $viewsvn->template->fetch('file_change') . '";'); - } - - return $files; - } - - // ################################################################### - /** - * Generates a clean revision number - * - * @access public - * - * @param integer Revision number - * - * @return mixed Cleaned revision or HEAD - */ - function rev($revision) - { - if (($revision = intval($revision)) < 1) - { - $revision = 'HEAD'; - } - return $revision; - } -} - -/*=====================================================================*\ -|| ################################################################### -|| # $HeadURL$ -|| # $Id$ -|| ################################################################### -\*=====================================================================*/ -?> \ No newline at end of file diff --git a/templates/default/diff.tpl b/templates/default/diff.tpl index 923d0bb..b5612e9 100644 --- a/templates/default/diff.tpl +++ b/templates/default/diff.tpl @@ -2,8 +2,8 @@ $doctype $headinclude - - + + {@"Diff"} @@ -20,10 +20,10 @@ $header
-
{@"Revision"}: $log[revision]
-
{@"Author"}: $log[author]
-
{@"Date"}: $log[date]
-
{@"Message"}: $log[message_clean]
+
{@"Revision"}: $revision->revision
+
{@"Author"}: $revision->author
+
{@"Date"}: $revision->datetime
+
{@"Message"}: $revision->message
{@"File Changes"}
-- 2.22.5