// ###################################################################
-$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']);
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']))
{
/**
* Raw unified diff text
- * @var string
+ * @var array
*/
private $raw;
*/
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
*/
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)
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;
}
// ###################################################################
*/
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++;
}
$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--;
}