repo = $repo; $this->diff = $diff; $this->lines = preg_split("/\015\012|\015|\012/", $diff); } public function parse() { $current_file = ''; $current_chunk = 0; $lline = 0; $rline = 0; $files = array(); foreach ($this->lines as $line) { if (0 === strpos($line, 'diff --git a')) { $current_file = self::getFile($line); $files[$current_file] = array(); $files[$current_file]['chunks'] = array(); $files[$current_file]['chunks_def'] = array(); $current_chunk = 0; continue; } if (0 === strpos($line, 'Index: ')) { $current_file = self::getSvnFile($line); $files[$current_file] = array(); $files[$current_file]['chunks'] = array(); $files[$current_file]['chunks_def'] = array(); $current_chunk = 0; continue; } if (0 === strpos($line, '@@ ')) { $files[$current_file]['chunks_def'][] = self::getChunk($line); $files[$current_file]['chunks'][] = array(); $current_chunk++; $lline = $files[$current_file]['chunks_def'][$current_chunk-1][0][0]; $rline = $files[$current_file]['chunks_def'][$current_chunk-1][1][0]; continue; } if (0 === strpos($line, '---') or 0 === strpos($line, '+++')) { continue; } if (0 === strpos($line, '-')) { $files[$current_file]['chunks'][$current_chunk-1][] = array($lline, '', substr($line, 1)); $lline++; continue; } if (0 === strpos($line, '+')) { $files[$current_file]['chunks'][$current_chunk-1][] = array('', $rline, substr($line, 1)); $rline++; continue; } if (0 === strpos($line, ' ')) { $files[$current_file]['chunks'][$current_chunk-1][] = array($lline, $rline, substr($line, 1)); $rline++; $lline++; continue; } } $this->files = $files; return $files; } public static function getFile($line) { $line = substr(trim($line), 10); $n = (int) strlen($line)/2; return trim(substr($line, 3, $n-3)); } public static function getSvnFile($line) { return substr(trim($line), 7); } /** * Return the html version of a parsed diff. */ public function as_html() { $out = ''; foreach ($this->files as $filename=>$file) { $out .= "\n".''."\n"; $out .= ''."\n"; $cc = 1; foreach ($file['chunks'] as $chunk) { foreach ($chunk as $line) { if ($line[0] and $line[1]) { $class = 'diff-c'; } elseif ($line[0]) { $class = 'diff-r'; } else { $class = 'diff-a'; } $line_content = $this->padLine(Pluf_esc($line[2])); $out .= sprintf(''."\n", $line[0], $line[1], $class, $line_content); } if (count($file['chunks']) > $cc) $out .= ''."\n"; $cc++; } $out .= '
'.Pluf_esc($filename).'
%s%s%s
...... 
'; } return $out; } public function padLine($line) { $n = strlen($line); for ($i=0;$i<$n;$i++) { if (substr($line, $i, 1) != ' ') { break; } } return str_repeat(' ', $i).substr($line, $i); } /** * @return array array(array(start, n), array(start, n)) */ public static function getChunk($line) { $elts = split(' ', $line); $res = array(); for ($i=1;$i<3;$i++) { $res[] = split(',', trim(substr($elts[$i], 1))); } return $res; } }