- Rewrote the Diff class to be much more easy-to-read and extend
authorRobert Sesek <rsesek@bluestatic.org>
Mon, 23 Apr 2007 00:19:34 +0000 (00:19 +0000)
committerRobert Sesek <rsesek@bluestatic.org>
Mon, 23 Apr 2007 00:19:34 +0000 (00:19 +0000)
- Cleaned up diff.php

diff.php
includes/class_diff.php

index 64859a7fae92ec8d484040cc93f23139e3a50d4d..32e0837a855f710628cb4b979ea97e6c8a9f210e 100644 (file)
--- a/diff.php
+++ b/diff.php
@@ -41,7 +41,7 @@ $link['log'] = ConstructLink('log', $input->in['repos'], $input->in['path'], $in
 
 // ###################################################################
 
-$show['fullchangeset'] = ($input->in['path'] == '' OR $input->in['path'] == '/');
+$show['fullchangeset'] = !($input->in['path'] == '' OR $input->in['path'] == '/');
 if ($show['fullchangeset'])
 {
        $link['changeset'] = ConstructLink('diff', $input->in['repos'], null, $input->in['rev']);
@@ -67,50 +67,46 @@ foreach ($diff->fetch() AS $filename => $file)
                continue;
        }
        
-       $props = $file['props'];
-       $show['props'] = (bool)$props;
-       unset($file['props']);
-       
-       foreach ($file AS $hunk)
+       foreach ($file['lines'] AS $hunk)
        {
                $lines = '';
+               
+               $show['hunk'] = true;
+               $low = $file['revision']['low'];
+               $high = $file['revision']['high'];
+               
+               $filename = (preg_match('/' . preg_quote($filename, '/') . '$/', $input->in['path']) ? $input->in['path'] : BSFunctions::FetchSourcePath($input->in['path']) . $filename);
+               $rlow = ConstructLink('view', $input->in['repos'], $filename, $low);
+               $rhigh = ConstructLink('view', $input->in['repos'], $filename, $high);
+               eval('$lines .= "' . $template->fetch('diff_line') . '";');
+               
                foreach ($hunk AS $key => $line)
                {
                        $show['hunk'] = false;
-                       if ($key == 'hunk' AND isset($line['old']))
+                       if ($line['act'] == '+')
+                       {
+                               $class = 'diff_add';
+                       }
+                       else if ($line['act'] == '-')
                        {
-                               $filepath = ($isdir ? $controller->path . $filename : $controller->path);
-                               // $rlow = ConstructLink('view', $input->in['repos'], $filename, $)
-                               $high = $revision->revision;
-                               $rhigh = ConstructLink('view', $input->in['repos'], $filename, $revision->revision);
-                               $show['hunk'] = true;
+                               $class = 'diff_del';
                        }
                        else
                        {
-                               if ($line['act'] == '+')
-                               {
-                                       $class = 'diff_add';
-                               }
-                               else if ($line['act'] == '-')
-                               {
-                                       $class = 'diff_del';
-                               }
-                               else
-                               {
-                                       $class = 'diff_norm';
-                               }
-                               
-                               $line['line_clean'] = FormatCode($line['line']);
+                               $class = 'diff_norm';
                        }
                        
+                       $line['line_clean'] = FormatCode($line['line']);
+                       
                        eval('$lines .= "' . $template->fetch('diff_line') . '";');
                }
                eval('$hunktpl .= "' . $template->fetch('diff_hunk') . '";');
        }
        
-       if (is_array($props))
+       if (is_array($file['props']))
        {
-               foreach ($props AS $name => $values)
+               $show['props'] = true;
+               foreach ($file['props'] AS $name => $values)
                {
                        // modified
                        if (isset($values['add']) AND isset($values['del']))
index c8e78936367e401f01b13c3faa608270939c6275..9fd43e62d0e5a8d262d97c4575fce25ce0645184 100644 (file)
@@ -35,7 +35,7 @@ class Diff
 {
        /**
        * Raw unified diff text
-       * @var string
+       * @var array
        */
        private $raw;
        
@@ -45,6 +45,30 @@ class Diff
        */
        private $index;
        
+       /**
+       * The array index of where capturing of diff data starts
+       * @var integer
+       */
+       private $captureStart = 0;
+       
+       /**
+       * Current hunk that is being processed
+       * @var integer
+       */
+       private $hunkId = 0;
+       
+       /**
+       * The lines on which hunks start
+       * @var array
+       */
+       private $hunkLines = array('old' => array('line' => 0, 'count' => 0), 'new' => array('line' => 0, 'count' => 0));
+       
+       /**
+       * The parsed diff output
+       * @var array
+       */
+       private $diff = array();
+       
        // ###################################################################
        /**
        * Constructor
@@ -65,61 +89,90 @@ class Diff
        */
        public function fetch()
        {
-               global $viewsvn;
+               for ($i = 0; $i < sizeof($this->raw); $i++)
+               {
+                       $line = $this->raw[$i];
+                       
+                       if (preg_match('/^Index: (.*)/', $line, $index))
+                       {
+                               $this->_processFile(array_slice($this->raw, $this->captureStart, $i - $this->captureStart));
+                               $this->captureStart = $i;
+                               $this->index = $index[1];
+                       }
+               }
+               $this->_processFile(array_slice($this->raw, $this->captureStart));
                
-               $chunk = 0;
-               $indexcounter = null;
-               $curprop = '';
+               return $this->diff;
+       }
+       
+       // ###################################################################
+       /**
+       * Processes a file part of a diff
+       *
+       * @param        array   An array of lines that make up a file chunk
+       */
+       private function _processFile($lines)
+       {
+               preg_match_all('/[\-\+]{3}\s+(.*)\s+\(revision ([0-9]*)\)/', $lines[2] . "\n" . $lines[3], $revs);
+               $this->diff[$this->index]['revision']['low'] = $revs[2][0];
+               $this->diff[$this->index]['revision']['high'] = $revs[2][1];
                
-               $delstack = array();
+               $this->hunkId = 0;
                
-               foreach ($this->raw AS $line)
+               $captureStart = 4;
+               for ($i = 4; $i < sizeof($lines); $i++)
                {
-                       if (preg_match('#^@@ \-([0-9]*),([0-9]*) \+([0-9]*),([0-9]*) @@$#', $line, $bits))
-                       {
-                               $property = false;
-                               $delstack = array();
-                               $this->diff["$index"][ ++$chunk ]['hunk'] = array('old' => array('line' => $bits[1], 'count' => $bits[2]), 'new' => array('line' => $bits[3], 'count' => $bits[4]));
-                               $lines['old'] = $this->diff["$index"]["$chunk"]['hunk']['old']['line'] - 1;
-                               $lines['new'] = $this->diff["$index"]["$chunk"]['hunk']['new']['line'] - 1;
-                               continue;
-                       }
-                       else if (preg_match('#^Property changes on: (.*?)$#', $line, $bits))
-                       {
-                               $property = true;
-                               $index = $bits[1];
-                               $this->diff["$index"]['props'] = array();
-                               continue;
-                       }
+                       $line = $lines[$i];
                        
-                       if ($indexcounter <= 3 AND $indexcounter !== null)
+                       if (preg_match('/^@@ \-([0-9]*),([0-9]*) \+([0-9]*),([0-9]*) @@/', $line, $hunkHead))
                        {
-                               $indexcounter++;
-                               continue;
+                               $this->hunkLines = array('old' => array('line' => $hunkHead[1], 'count' => $hunkHead[2]), 'new' => array('line' => $hunkHead[3], 'count' => $hunkHead[4]));
+                               $this->_processHunk(array_slice($lines, $captureStart, $i - $captureStart));
+                               $captureStart = $i;
+                               $this->hunkId++;
                        }
-                       else if ($indexcounter == 3)
+                       else if (preg_match('#^__*_$#', $line))
                        {
-                               $indexcounter = null;
-                               continue;
+                               $this->_processHunk(array_slice($lines, $captureStart, $i - $captureStart));
+                               $this->_processProperties(array_slice($lines, $i));
+                               return;
                        }
+               }
+               $this->_processHunk(array_slice($lines, $captureStart));
+       }
+       
+       // ###################################################################
+       /**
+       * This processes an individual hunk of a file
+       *
+       * @param        array   Array of lines
+       */
+       private function _processHunk($lines)
+       {
+               $delstack = array();
+               for ($i = 1; $i < sizeof($lines); $i++)
+               {
+                       $line = $lines[$i];
                        
-                       if (preg_match('#^([\+\- ])(.*)#', $line, $matches) AND !$property)
+                       if (preg_match('/^([\+\- ])(.*)/', $line, $matches))
                        {
-                               $act = $matches[1];
+                               $action = $matches[1];
                                $content = $matches[2];
                                
-                               if ($act == ' ')
+                               // leader line
+                               if ($action == ' ')
                                {
-                                       $this->diff["$index"]["$chunk"][] = array(
+                                       $this->diff[$this->index]['lines'][$this->hunkId][] = array(
                                                'line'          => $content,
                                                'act'           => '',
-                                               'oldlineno'     => ++$lines['old'],
-                                               'newlineno'     => ++$lines['new']
+                                               'oldlineno'     => ++$this->hunkLines['old']['line'],
+                                               'newlineno'     => ++$this->hunkLines['new']['line']
                                        );
                                        
                                        $delstack = array();
                                }
-                               else if ($act == '+')
+                               // addition
+                               else if ($action == '+')
                                {               
                                        // potential line delta
                                        if (sizeof($delstack) > 0)
@@ -131,100 +184,80 @@ class Diff
                                                        if (strlen($lastline['line']) > ($delta['start'] - $delta['end']))
                                                        {
                                                                $end = strlen($lastline['line']) + $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);
+                                                               $this->diff[$this->index]['lines'][$this->hunkId][$lastline['index']]['line'] = substr($lastline['line'], 0, $delta['start']) . $change . substr($lastline['line'], $end);
                                                        }
                                                        
                                                        if (strlen($content) > $delta['start'] - $delta['end'])
                                                        {
                                                                $end = strlen($content) + $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);
                                                        }
                                                }
                                        }
                                        
-                                       $this->diff["$index"]["$chunk"][] = array(
+                                       $this->diff[$this->index]['lines'][$this->hunkId][] = array(
                                                'line'          => $content,
                                                'act'           => '+',
-                                               'oldlineno'     => '',
-                                               'newlineno'     => ++$lines['new']
+                                               'oldlineno'     => 0,
+                                               'newlineno'     => ++$this->hunkLines['new']['line']
                                        );
                                }
-                               else if ($act == '-')
+                               // deletion
+                               else if ($action == '-')
                                {
-                                       $this->diff["$index"]["$chunk"][] = $thearray = array(
+                                       $this->diff[$this->index]['lines'][$this->hunkId][] = $temp = array(
                                                'line'          => $content,
                                                'act'           => '-',
-                                               'oldlineno'     => ++$lines['old'],
-                                               'newlineno'     => ''
+                                               'oldlineno'     => ++$this->hunkLines['old']['line'],
+                                               'newlineno'     => 0
                                        );
                                        
-                                       $key = sizeof($this->diff["$index"]["$chunk"]) - 2;
-                                       $thearray['INDEX'] = $key;
-                                       
-                                       array_push($delstack, $thearray);
+                                       $temp['index'] = sizeof($this->diff[$this->index]['lines'][$this->hunkId]) - 1;
+                                       array_push($delstack, $temp);
                                }
                        }
-                       // whitespace lines
+               }
+       }
+       
+       // ###################################################################
+       /**
+       * Processes properties
+       *
+       * @param        array   Lines of properties
+       */
+       private function _processProperties($lines)
+       {
+               $curprop = '';
+               $mode = '';
+               $captureStart = 1;
+               for ($i = 1; $i < sizeof($lines); $i++)
+               {
+                       $line = $lines[$i];
+                       if (preg_match('#Name: (.*?)$#', $line, $matches))
+                       {
+                               $curprop = $matches[1];
+                               BSRegister::Debug("prop: $curprop");
+                       }
                        else
                        {
-                               if (preg_match('#^Index: (.*?)$#', $line, $matches))
+                               if (preg_match('#^\s+?\+(.*)#', $line, $matches))
                                {
-                                       $index = $matches[1];
-                                       $indexcounter = 1;
-                                       $chunk = 0;
-                                       continue;
+                                       $mode = 'add';
+                                       $this->diff[$this->index]['props'][$curprop]['add'] .= $matches[1];
                                }
-                               
-                               if ($property)
+                               else if (preg_match('#^\s+?\-(.*)#', $line, $matches))
                                {
-                                       if (preg_match('#^__*_$#', trim($line)))
-                                       {
-                                               BSRegister::Debug("skipping: $line");
-                                               continue;
-                                       }
-                                       
-                                       if (preg_match('#Name: (.*?)$#', $line, $matches))
-                                       {
-                                               $curprop = $matches[1];
-                                               BSRegister::Debug("prop: $curprop");
-                                               continue;
-                                       }
-                                       else
-                                       {
-                                               if (preg_match('#^\s+?\+(.*)#', $line, $matches))
-                                               {
-                                                       $mode = 'add';
-                                                       $this->diff["$index"]['props']["$curprop"]['add'] .= $matches[1];
-                                               }
-                                               else if (preg_match('#^\s+?\-(.*)#', $line, $matches))
-                                               {
-                                                       $mode = 'del';
-                                                       $this->diff["$index"]['props']["$curprop"]['del'] .= $matches[1];
-                                               }
-                                               else if (!preg_match('#^\s+[\+\- ](.*)#', $line) AND trim($line) != '')
-                                               {
-                                                       $this->diff["$index"]['props']["$curprop"]["$mode"] .= "\n" . $line;
-                                               }
-                                               continue;
-                                       }
+                                       $mode = 'del';
+                                       $this->diff[$this->index]['props'][$curprop]['del'] .= $matches[1];
+                               }
+                               else if (!preg_match('#^\s+[\+\- ](.*)#', $line) AND trim($line) != '')
+                               {
+                                       $this->diff[$this->index]['props'][$curprop][$mode] .= "\n" . $line;
                                }
-                               
-                               $this->diff["$index"]["$chunk"][] = array(
-                                       'line'          => '',
-                                       'act'           => '',
-                                       'oldlineno'     => ++$lines['old'],
-                                       'newlineno'     => ++$lines['new']
-                               );
-                               
-                               $delstack = array();
                        }
                }
-               
-               return $this->diff;
        }
        
        // ###################################################################
@@ -238,14 +271,10 @@ class Diff
        */
        private function _fetchDiffExtent($old, $new)
        {
-               global $viewsvn;
-               
                $start = 0;
                $min = min(strlen($old), strlen($new));
                
-               BSRegister::Debug("min1 = $min");
-               
-               while ($start < $min AND $old["$start"] == $new["$start"])
+               while ($start < $min AND $old[$start] == $new[$start])
                {
                        $start++;
                }
@@ -253,11 +282,7 @@ class Diff
                $end = -1;
                $min = $min - $start;
                
-               BSRegister::Debug("min2 = $min");
-               
-               BSRegister::Debug("checking: " . $old[ strlen($old) + $end ] . ' ==  ' . $new[ strlen($new) + $end ]);
-               
-               while (-$end <= $min AND $old[ strlen($old) + $end ] == $new[ strlen($new) + $end ])
+               while (-$end <= $min AND $old[strlen($old) + $end] == $new[strlen($new) + $end])
                {
                        $end--;
                }