2 /*=====================================================================*\
3 || ###################################################################
4 || # ViewSVN [#]version[#]
5 || # Copyright ©2002-[#]year[#] Blue Static
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version [#]gpl[#] of the License.
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
25 * This class parses a diff file from a unified diff file and turns it
26 * into a HTML-prettied output
29 * @copyright Copyright (c)2002 - [#]year[#], Blue Static
37 * Raw unified diff text
43 * The current index (file)
49 * The array index of where capturing of diff data starts
52 private $captureStart = 0;
55 * Current hunk that is being processed
61 * The lines on which hunks start
64 private $hunkLines = array('old' => array('line' => 0, 'count' => 0), 'new' => array('line' => 0, 'count' => 0));
67 * The parsed diff output
70 private $diff = array();
72 // ###################################################################
76 * @param string Raw unified diff output
78 public function __construct($raw)
83 // ###################################################################
85 * This function initiates the parsing process and returns the output
86 * in hunks, line-by-line
88 * @return array Array of outputted hunked information
90 public function fetch()
92 $this->diff
= array();
94 for ($i = 0; $i < sizeof($this->raw
); $i++
)
96 $line = $this->raw
[$i];
98 if (preg_match('/^Index: (.*)/', $line, $index))
100 $this->_processFile(array_slice($this->raw
, $this->captureStart
, $i - $this->captureStart
));
101 $this->captureStart
= $i;
102 $this->index
= $index[1];
104 else if (preg_match('/Property changes on: (.*)/', $line, $index))
106 $this->index
= $index[1];
107 $this->_processProperties(array_slice($this->raw
, 2));
110 $this->_processFile(array_slice($this->raw
, $this->captureStart
));
115 // ###################################################################
117 * Processes a file part of a diff
119 * @param array An array of lines that make up a file chunk
121 private function _processFile($lines)
123 preg_match_all('/[\-\+]{3}\s+(.*)\s+\(revision ([0-9]*)\)/', $lines[2] . "\n" . $lines[3], $revs);
124 $this->diff
[$this->index
]['revision']['low'] = $revs[2][0];
125 $this->diff
[$this->index
]['revision']['high'] = $revs[2][1];
131 for ($i = 4; $i < sizeof($lines); $i++
)
135 if (preg_match('/^@@ \-([0-9]*),([0-9]*) \+([0-9]*),([0-9]*) @@/', $line, $hunkHead))
137 $this->hunkLines
= array('old' => array('line' => $hunkHead[1], 'count' => $hunkHead[2]), 'new' => array('line' => $hunkHead[3], 'count' => $hunkHead[4]));
138 $this->_processHunk(array_slice($lines, $captureStart, $i - $captureStart));
142 else if (preg_match('#^__*_$#', $line))
144 $this->_processHunk(array_slice($lines, $captureStart, $i - $captureStart));
145 $this->_processProperties(array_slice($lines, $i));
149 $this->_processHunk(array_slice($lines, $captureStart));
152 // ###################################################################
154 * This processes an individual hunk of a file
156 * @param array Array of lines
158 private function _processHunk($lines)
161 for ($i = 1; $i < sizeof($lines); $i++
)
165 if (preg_match('/^([\+\- ])(.*)/', $line, $matches))
167 $action = $matches[1];
168 $content = $matches[2];
173 $this->diff
[$this->index
]['lines'][$this->hunkId
][] = array(
176 'oldlineno' => ++
$this->hunkLines
['old']['line'],
177 'newlineno' => ++
$this->hunkLines
['new']['line']
183 else if ($action == '+')
185 // potential line delta
186 if (sizeof($delstack) > 0)
188 $lastline = array_shift($delstack);
190 if ($delta = @$this->_fetchDiffExtent($lastline['line'], $content))
192 if (strlen($lastline['line']) > ($delta['start'] - $delta['end']))
194 $end = strlen($lastline['line']) +
$delta['end'];
195 $change = '{@-' . '-}' . substr($lastline['line'], $delta['start'], $end - $delta['start']) . '{/@-' . '-}';
196 $this->diff
[$this->index
]['lines'][$this->hunkId
][$lastline['index']]['line'] = substr($lastline['line'], 0, $delta['start']) . $change . substr($lastline['line'], $end);
199 if (strlen($content) > $delta['start'] - $delta['end'])
201 $end = strlen($content) +
$delta['end'];
202 $change = '{@+' . '+}' . substr($content, $delta['start'], $end - $delta['start']) . '{/@+' . '+}';
203 $content = substr($content, 0, $delta['start']) . $change . substr($content, $end);
208 $this->diff
[$this->index
]['lines'][$this->hunkId
][] = array(
212 'newlineno' => ++
$this->hunkLines
['new']['line']
216 else if ($action == '-')
218 $this->diff
[$this->index
]['lines'][$this->hunkId
][] = $temp = array(
221 'oldlineno' => ++
$this->hunkLines
['old']['line'],
225 $temp['index'] = sizeof($this->diff
[$this->index
]['lines'][$this->hunkId
]) - 1;
226 array_push($delstack, $temp);
232 // ###################################################################
234 * Processes properties
236 * @param array Lines of properties
238 private function _processProperties($lines)
243 for ($i = 1; $i < sizeof($lines); $i++
)
246 if (preg_match('#Name: (.*?)$#', $line, $matches))
248 $curprop = $matches[1];
249 BSRegister
::Debug("prop: $curprop");
253 if (preg_match('#^\s+?\+(.*)#', $line, $matches))
256 $this->diff
[$this->index
]['props'][$curprop]['add'] .= $matches[1];
258 else if (preg_match('#^\s+?\-(.*)#', $line, $matches))
261 $this->diff
[$this->index
]['props'][$curprop]['del'] .= $matches[1];
263 else if (!preg_match('#^\s+[\+\- ](.*)#', $line) AND trim($line) != '')
265 $this->diff
[$this->index
]['props'][$curprop][$mode] .= "\n" . $line;
271 // ###################################################################
273 * Returns the amount of change that occured between two lines
275 * @param string Old line
276 * @param string New line
278 * @return array Difference of positions
280 private function _fetchDiffExtent($old, $new)
283 $min = min(strlen($old), strlen($new));
285 while ($start < $min AND $old[$start] == $new[$start])
291 $min = $min - $start;
293 while (-$end <= $min AND $old[strlen($old) +
$end] == $new[strlen($new) +
$end])
298 return array('start' => $start, 'end' => $end +
1);
302 /*=====================================================================*\
303 || ###################################################################
306 || ###################################################################
307 \*=====================================================================*/