Added a better commit diff.
This commit is contained in:
parent
cb15f036fe
commit
80ce87009e
140
src/IDF/Diff.php
Normal file
140
src/IDF/Diff.php
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<?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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
57
src/IDF/Tests/TestDiff.php
Normal file
57
src/IDF/Tests/TestDiff.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?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 ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the diff parser.
|
||||||
|
*/
|
||||||
|
class IDF_Tests_TestDiff extends UnitTestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct('Test the diff parser.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetFile()
|
||||||
|
{
|
||||||
|
$lines = array(
|
||||||
|
'diff --git a/src/IDF/Form/Register.php b/src/IDF/Form/Register.php',
|
||||||
|
'diff --git a/src/IDF/Form/RegisterConfirmation.php b/src/IDF/Form/RegisterConfirmation.php',
|
||||||
|
'diff --git a/src/IDF/Form/RegisterInputKey.php b/src/IDF/Form/RegisterInputKey.php',
|
||||||
|
'diff --git a/src/IDF/Views.php b/src/IDF/Views.php',
|
||||||
|
'diff --git a/src/IDF/conf/views.php b/src/IDF/conf/views.php',
|
||||||
|
);
|
||||||
|
$files = array(
|
||||||
|
'src/IDF/Form/Register.php',
|
||||||
|
'src/IDF/Form/RegisterConfirmation.php',
|
||||||
|
'src/IDF/Form/RegisterInputKey.php',
|
||||||
|
'src/IDF/Views.php',
|
||||||
|
'src/IDF/conf/views.php',
|
||||||
|
);
|
||||||
|
$i = 0;
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
$this->assertEqual($files[$i], IDF_Diff::getFile($line));
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -162,15 +162,13 @@ class IDF_Views_Source
|
|||||||
$title = sprintf('%s Commit Details', (string) $request->project);
|
$title = sprintf('%s Commit Details', (string) $request->project);
|
||||||
$page_title = sprintf('%s Commit Details - %s', (string) $request->project, $commit);
|
$page_title = sprintf('%s Commit Details - %s', (string) $request->project, $commit);
|
||||||
$cobject = $git->getCommit($commit);
|
$cobject = $git->getCommit($commit);
|
||||||
require_once 'Text/Highlighter.php';
|
$diff = new IDF_Diff($cobject->changes);
|
||||||
$th = new Text_Highlighter();
|
$diff->parse();
|
||||||
$h = $th->factory('DIFF');
|
|
||||||
$changes = $h->highlight($cobject->changes);
|
|
||||||
return Pluf_Shortcuts_RenderToResponse('source/commit.html',
|
return Pluf_Shortcuts_RenderToResponse('source/commit.html',
|
||||||
array(
|
array(
|
||||||
'page_title' => $page_title,
|
'page_title' => $page_title,
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'changes' => $changes,
|
'diff' => $diff,
|
||||||
'cobject' => $cobject,
|
'cobject' => $cobject,
|
||||||
'commit' => $commit,
|
'commit' => $commit,
|
||||||
'branches' => $branches,
|
'branches' => $branches,
|
||||||
|
@ -17,9 +17,20 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th><strong>{trans 'Message:'}</strong></th><td>{issuetext $cobject.title, $project}{if isset($cobject.full_message)}<br /><br />{issuetext $cobject.full_message, $project}{/if}</td>
|
<th><strong>{trans 'Message:'}</strong></th><td>{issuetext $cobject.title, $project}{if isset($cobject.full_message)}<br /><br />{issuetext $cobject.full_message, $project}{/if}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th><strong>{trans 'Files:'}</strong></th>
|
||||||
|
<td>
|
||||||
|
{foreach $diff.files as $filename=>$diffdef}
|
||||||
|
{assign $ndiff = count($diffdef['chunks'])}
|
||||||
|
<a href="#diff-{$filename|md5}">{$filename}</a> (<a href="#diff-{$filename|md5}">{blocktrans $ndiff}{$ndiff} diff{plural}{$ndiff} diffs{/blocktrans}</a>)<br />
|
||||||
|
{/foreach}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<h2>{trans 'Change Details'}</h2>
|
<h2>{trans 'Change Details'}</h2>
|
||||||
{$changes|safe}
|
|
||||||
|
{$diff.as_html()|safe}
|
||||||
|
|
||||||
{/block}
|
{/block}
|
||||||
{block context}
|
{block context}
|
||||||
<p><strong>{trans 'Branches:'}</strong><br />
|
<p><strong>{trans 'Branches:'}</strong><br />
|
||||||
|
@ -386,24 +386,61 @@ table.commit td, table.commit th {
|
|||||||
/**
|
/**
|
||||||
* syntax highlighting of diffs
|
* syntax highlighting of diffs
|
||||||
*/
|
*/
|
||||||
div.hl-main {
|
table.diff {
|
||||||
font-family: monospace;
|
border-bottom: 1px solid #d3d7cf;
|
||||||
white-space: pre;
|
width: 100%;
|
||||||
border: 1px solid #d3d7cf;
|
|
||||||
padding: 1em;
|
|
||||||
}
|
}
|
||||||
span.hl-string {
|
|
||||||
|
table.diff th {
|
||||||
|
background-color: #e4e8E0;
|
||||||
|
vertical-align: top;
|
||||||
|
border-color: #d3d7cf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
table.diff tr {
|
||||||
|
border-left: 1px solid #d3d7cf;
|
||||||
|
border-right: 1px solid #d3d7cf;
|
||||||
|
border-bottom: none;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.diff td {
|
||||||
|
font-size: 90%;
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 1px;
|
||||||
|
border-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.diff td.diff-lc {
|
||||||
|
text-align: right;
|
||||||
|
padding: 1px 5px;
|
||||||
|
border-color: inherit;
|
||||||
|
border-top: 1px solid #d3d7cf;
|
||||||
|
border-bottom: 1px solid #d3d7cf;
|
||||||
|
width: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.diff-a {
|
||||||
background-color: #dfd;
|
background-color: #dfd;
|
||||||
}
|
}
|
||||||
span.hl-quotes {
|
|
||||||
|
td.diff-r {
|
||||||
background-color: #fdd;
|
background-color: #fdd;
|
||||||
}
|
}
|
||||||
span.hl-reserved, span.hl-var {
|
|
||||||
font-weight: bold;
|
td.diff-a, td.diff-r, td.diff-c {
|
||||||
|
border-bottom: none;
|
||||||
|
border-top: none;
|
||||||
}
|
}
|
||||||
span.hl-default {
|
|
||||||
color: #888a85;
|
table.diff tr.diff-next {
|
||||||
|
background-color: #e4e8E0;
|
||||||
|
vertical-align: top;
|
||||||
|
text-align: right;
|
||||||
|
border-color: #d3d7cf;
|
||||||
}
|
}
|
||||||
div.hl-main span {
|
|
||||||
line-height: 1.3;
|
table.diff tr.diff-next td {
|
||||||
|
padding: 1px 5px;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user