0,0 → 1,349 |
<?php |
// WebSVN - Subversion repository viewing via the web using PHP |
// Copyright (C) 2004-2006 Tim Armes |
// |
// This program 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. |
// |
// This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
// |
// -- |
// |
// diff_inc.php |
// |
// Diff to files |
|
if (!defined('USE_AUTOLOADER')) { |
@include_once 'Horde/String.php'; |
@include_once 'Horde/Text/Diff.php'; |
@include_once 'Horde/Text/Diff/Mapped.php'; |
@include_once 'Horde/Text/Diff/Engine/Native.php'; |
@include_once 'Horde/Text/Diff/Op/Base.php'; |
@include_once 'Horde/Text/Diff/Op/Copy.php'; |
@include_once 'Horde/Text/Diff/Op/Delete.php'; |
@include_once 'Horde/Text/Diff/Op/Add.php'; |
@include_once 'Horde/Text/Diff/Op/Change.php'; |
@include_once 'Horde/Text/Diff/Renderer.php'; |
@include_once 'Horde/Text/Diff/Renderer/Unified.php'; |
} |
include_once 'include/diff_util.php'; |
|
$arrayBased = false; |
$fileBased = false; |
|
class ListingHelper { |
var $_listing = array(); |
var $_index = 0; |
var $_blockStart = false; |
|
function _add($text1, $lineno1, $class1, $text2, $lineno2, $class2) { |
$listing = &$this->_listing; |
$index = &$this->_index; |
|
$listvar = &$listing[$index]; |
$listvar['rev1diffclass'] = $class1; |
$listvar['rev2diffclass'] = $class2; |
|
$listvar['rev1line'] = $text1; |
$listvar['rev2line'] = $text2; |
|
$listvar['rev1lineno'] = $lineno1; |
$listvar['rev2lineno'] = $lineno2; |
$listvar['startblock'] = $this->_blockStart; |
$this->_blockStart = false; |
$index++; |
} |
|
function addDeletedLine($text, $lineno) { |
$this->_add($text, $lineno, 'diffdeleted', ' ', '-', 'diffempty'); |
} |
|
function addAddedLine($text, $lineno) { |
$this->_add(' ', '-', 'diffempty', $text, $lineno, 'diffadded'); |
} |
|
function addChangedLine($text1, $lineno1, $text2, $lineno2) { |
$this->_add($text1, $lineno1, 'diffchanged', $text2, $lineno2, 'diffchanged'); |
} |
|
// note that $text1 do not need to be equal $text2 if $ignoreWhitespace is true |
function addLine($text1, $lineno1, $text2, $lineno2) { |
$this->_add($text1, $lineno1, 'diff', $text2, $lineno2, 'diff'); |
} |
|
function startNewBlock() { |
$this->_blockStart = true; |
} |
|
function getListing() { |
return $this->_listing; |
} |
} |
|
function nextLine(&$obj) { |
global $arrayBased, $fileBased; |
if ($arrayBased) return array_shift($obj); |
if ($fileBased) return fgets($obj); |
return ''; |
} |
|
function endOfFile(&$obj) { |
global $arrayBased, $fileBased; |
if ($arrayBased) return count($obj) == 0; |
if ($fileBased) return feof($obj); |
return true; |
} |
|
|
function getWrappedLineFromFile($file, $is_highlighted) { |
$line = fgets($file); |
if ($line === false) return false; |
$line = toOutputEncoding($line); |
if (!$is_highlighted) { |
$line = escape($line); |
} |
$line = rtrim($line, "\n\r"); |
if (strip_tags($line) === '') $line = ' '; |
return wrapInCodeTagIfNecessary($line); |
} |
|
function diff_result($all, $highlighted, $newtname, $oldtname, $obj, $ignoreWhitespace) { |
$ofile = fopen($oldtname, 'r'); |
$nfile = fopen($newtname, 'r'); |
|
// Get the first real line |
$line = nextLine($obj); |
|
$index = 0; |
$listingHelper = new ListingHelper(); |
|
$curoline = 1; |
$curnline = 1; |
|
$sensibleLineChanges = new SensibleLineChanges(new LineDiff($ignoreWhitespace)); |
|
while (!endOfFile($obj)) { |
// Get the first line of this range |
$oline = 0; |
sscanf($line, '@@ -%d', $oline); |
$line = substr($line, strpos($line, '+')); |
$nline = 0; |
sscanf($line, '+%d', $nline); |
|
while ($curoline < $oline || $curnline < $nline) { |
if ($curoline < $oline) { |
$text1 = getWrappedLineFromFile($ofile, $highlighted); |
$tmpoline = $curoline; |
$curoline++; |
} else { |
$tmpoline = '?'; |
$text1 = ' '; |
} |
|
if ($curnline < $nline) { |
$text2 = getWrappedLineFromFile($nfile, $highlighted); |
$tmpnline = $curnline; |
$curnline++; |
} else { |
$tmpnline = '?'; |
$text2 = ' '; |
} |
|
if ($all) { |
$listingHelper->addLine($text1, $tmpoline, $text2, $tmpnline); |
} |
} |
|
if (!$all && $line !== false) { |
$listingHelper->startNewBlock(); |
} |
|
$fin = false; |
while (!endOfFile($obj) && !$fin) { |
$line = nextLine($obj); |
if ($line === false || $line === '' || strncmp($line, '@@', 2) == 0) { |
$sensibleLineChanges->addChangesToListing($listingHelper, $highlighted); |
$fin = true; |
} else { |
$mod = $line[0]; |
$line = substr($line, 1); |
|
switch ($mod) { |
case '-': |
$text = getWrappedLineFromFile($ofile, $highlighted); |
$sensibleLineChanges->addDeletedLine($line, $text, $curoline); |
$curoline++; |
break; |
|
case '+': |
$text = getWrappedLineFromFile($nfile, $highlighted); |
$sensibleLineChanges->addAddedLine($line, $text, $curnline); |
$curnline++; |
break; |
|
default: |
$sensibleLineChanges->addChangesToListing($listingHelper, $highlighted); |
|
$text1 = getWrappedLineFromFile($ofile, $highlighted); |
$text2 = getWrappedLineFromFile($nfile, $highlighted); |
$listingHelper->addLine($text1, $curoline, $text2, $curnline); |
|
$curoline++; |
$curnline++; |
|
break; |
} |
} |
|
if (!$fin) { |
$index++; |
} |
} |
} |
$sensibleLineChanges->addChangesToListing($listingHelper, $highlighted); |
|
// Output the rest of the files |
if ($all) { |
while (!feof($ofile) || !feof($nfile)) { |
$noneof = false; |
|
$text1 = getWrappedLineFromFile($ofile, $highlighted); |
if ($text1 !== false) { |
$tmpoline = $curoline; |
$curoline++; |
$noneof = true; |
} else { |
$tmpoline = '-'; |
$text1 = ' '; |
} |
|
|
$text2 = getWrappedLineFromFile($nfile, $highlighted); |
if ($text2 !== false) { |
$tmpnline = $curnline; |
$curnline++; |
$noneof = true; |
} else { |
$tmpnline = '-'; |
$text2 = ' '; |
} |
|
if ($noneof) { |
$listingHelper->addLine($text1, $tmpoline, $text2, $tmpnline); |
} |
|
} |
} |
|
fclose($ofile); |
fclose($nfile); |
|
return $listingHelper->getListing(); |
} |
|
function command_diff($all, $ignoreWhitespace, $highlighted, $newtname, $oldtname, $newhlname, $oldhlname) { |
global $config, $lang, $arrayBased, $fileBased; |
|
$context = 5; |
|
if ($all) { |
// Setting the context to 0 makes diff generate the wrong line numbers! |
$context = 1; |
} |
|
if ($ignoreWhitespace) { |
$whitespaceFlag = ' -w'; |
} else { |
$whitespaceFlag = ''; |
} |
|
// Open a pipe to the diff command with $context lines of context: |
$cmd = $config->diff.$whitespaceFlag.' -U '.$context.' "'.$oldtname.'" "'.$newtname.'"'; |
$diff = runCommand($cmd, true); |
|
// Ignore the 3 header lines: |
$line = array_shift($diff); |
$line = array_shift($diff); |
|
$arrayBased = true; |
$fileBased = false; |
|
if ($highlighted) { |
$listing = diff_result($all, $highlighted, $newhlname, $oldhlname, $diff, $ignoreWhitespace); |
} else { |
$listing = diff_result($all, $highlighted, $newtname, $oldtname, $diff, $ignoreWhitespace); |
} |
|
return $listing; |
} |
|
function inline_diff($all, $ignoreWhitespace, $highlighted, $newtname, $oldtname, $newhlname, $oldhlname) { |
global $arrayBased, $fileBased; |
|
$context = 5; |
if ($all) { |
// Setting the context to 0 makes diff generate the wrong line numbers! |
$context = 1; |
} |
|
// modify error reporting level to suppress deprecated/strict warning "Assigning the return value of new by reference" |
$bckLevel = error_reporting(); |
$removeLevel = E_DEPRECATED; |
$modLevel = $bckLevel & (~$removeLevel); |
error_reporting($modLevel); |
|
// Create the diff class |
$fromLines = file($oldtname); |
$toLines = file($newtname); |
if (!$ignoreWhitespace) { |
$diff = new Horde_Text_Diff('Native', array($fromLines, $toLines)); |
} else { |
$whitespaces = array(' ', "\t", "\n", "\r"); |
$mappedFromLines = array(); |
foreach ($fromLines as $k => $line) { |
$line = rtrim($line, "\n\r"); |
$fromLines[$k] = $line; |
$mappedFromLines[] = str_replace($whitespaces, array(), $line); |
} |
$mappedToLines = array(); |
foreach ($toLines as $k => $line) { |
$line = rtrim($line, "\n\r"); |
$toLines[$k] = $line; |
$mappedToLines[] = str_replace($whitespaces, array(), $line); |
} |
$diff = new Horde_Text_Diff_Mapped('Native', array($fromLines, $toLines, $mappedFromLines, $mappedToLines)); |
} |
$renderer = new Horde_Text_Diff_Renderer_Unified(array('leading_context_lines' => $context, 'trailing_context_lines' => $context)); |
$rendered = explode("\n", $renderer->render($diff)); |
|
// restore previous error reporting level |
error_reporting($bckLevel); |
|
$arrayBased = true; |
$fileBased = false; |
if ($highlighted) { |
$listing = diff_result($all, $highlighted, $newhlname, $oldhlname, $rendered, $ignoreWhitespace); |
} else { |
$listing = diff_result($all, $highlighted, $newtname, $oldtname, $rendered, $ignoreWhitespace); |
} |
|
return $listing; |
} |
|
function do_diff($all, $ignoreWhitespace, $highlighted, $newtname, $oldtname, $newhlname, $oldhlname) { |
if ((!$ignoreWhitespace ? class_exists('Horde_Text_Diff') : class_exists('Horde_Text_Diff_Mapped')) |
&& class_exists('Horde_Text_Diff_Renderer_Unified')) { |
return inline_diff($all, $ignoreWhitespace, $highlighted, $newtname, $oldtname, $newhlname, $oldhlname); |
} else { |
return command_diff($all, $ignoreWhitespace, $highlighted, $newtname, $oldtname, $newhlname, $oldhlname); |
} |
} |