| <?php␊ | 
| /* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */␊ | 
| /*␊ | 
| # ***** BEGIN LICENSE BLOCK *****␊ | 
| # This file is part of InDefero, an open source project management application.␊ | 
| # Copyright (C) 2008 Céondo Ltd and contributors.␊ | 
| #␊ | 
| # InDefero is free software; you can redistribute it and/or modify␊ | 
| # it under the terms of the GNU General Public License as published by␊ | 
| # the Free Software Foundation; either version 2 of the License, or␊ | 
| # (at your option) any later version.␊ | 
| #␊ | 
| # InDefero is distributed in the hope that it will be useful,␊ | 
| # but WITHOUT ANY WARRANTY; without even the implied warranty of␊ | 
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the␊ | 
| # GNU General Public License for more details.␊ | 
| #␊ | 
| # You should have received a copy of the GNU General Public License␊ | 
| # along with this program; if not, write to the Free Software␊ | 
| # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA␊ | 
| #␊ | 
| # ***** END LICENSE BLOCK ***** */␊ | 
| ␊ | 
| /**␊ | 
| * Diff parser.␊ | 
| *␊ | 
| */␊ | 
| class IDF_Diff␊ | 
| {␊ | 
| public $repo = '';␊ | 
| public $diff = '';␊ | 
| protected $lines = array();␊ | 
| ␊ | 
| public $files = array();␊ | 
| ␊ | 
| public function __construct($diff, $repo='')␊ | 
| {␊ | 
| $this->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;␊ | 
| 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, '@@ ')) {␊ | 
| $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));␊ | 
| }␊ | 
| ␊ | 
| /**␊ | 
| * Return the html version of a parsed diff.␊ | 
| */␊ | 
| public function as_html()␊ | 
| {␊ | 
| $out = '';␊ | 
| foreach ($this->files as $filename=>$file) {␊ | 
| $out .= "\n".'<table class="diff" summary="">'."\n";␊ | 
| $out .= '<tr id="diff-'.md5($filename).'"><th colspan="3">'.Pluf_esc($filename).'</th></tr>'."\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';␊ | 
| }␊ | 
| $out .= sprintf('<tr class="diff-line"><td class="diff-lc">%s</td><td class="diff-lc">%s</td><td class="%s mono">%s</td></tr>'."\n", $line[0], $line[1], $class, Pluf_esc($line[2]));␊ | 
| }␊ | 
| if (count($file['chunks']) > $cc)␊ | 
| $out .= '<tr class="diff-next"><td>...</td><td>...</td><td> </td></tr>'."\n";␊ | 
| $cc++;␊ | 
| }␊ | 
| $out .= '</table>';␊ | 
| }␊ | 
| return $out;␊ | 
| }␊ | 
| ␊ | 
| /**␊ | 
| * @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;␊ | 
| }␊ | 
| ␊ | 
| } |