1,8 → 1,6 |
<?php |
# vim:et:ts=3:sts=3:sw=3:fdm=marker: |
|
// WebSVN - Subversion repository viewing via the web using PHP |
// Copyright © 2004-2006 Tim Armes, Matt Sicker |
// 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 |
11,12 → 9,12 |
// |
// 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 |
// 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 |
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
// |
// -- |
// |
25,334 → 23,212 |
// Show the differences between 2 revisions of a file. |
// |
|
require_once("include/setup.inc"); |
require_once("include/svnlook.inc"); |
require_once("include/utils.inc"); |
require_once("include/template.inc"); |
require_once 'include/setup.php'; |
require_once 'include/svnlook.php'; |
require_once 'include/utils.php'; |
require_once 'include/template.php'; |
|
$context = 5; |
require_once 'include/diff_inc.php'; |
|
$vars["action"] = $lang["DIFF"]; |
$all = (@$_REQUEST["all"] == 1)?1:0; |
$vars['action'] = $lang['DIFF']; |
$all = (@$_REQUEST['all'] == 1); |
$ignoreWhitespace = $config->getIgnoreWhitespacesInDiff(); |
|
if (array_key_exists('ignorews', $_REQUEST)) |
{ |
$ignoreWhitespace = (bool)$_REQUEST['ignorews']; |
} |
|
// Make sure that we have a repository |
if (!isset($rep)) |
if (!$rep) |
{ |
echo $lang["NOREP"]; |
exit; |
renderTemplate404('diff','NOREP'); |
} |
|
$svnrep = new SVNRepository($rep); |
|
// If there's no revision info, go to the lastest revision for this path |
$history = $svnrep->getLog($path, "", "", true); |
$youngest = $history->entries[0]->rev; |
$history = $svnrep->getLog($path, 'HEAD', 1, true, 2, ($path == '/') ? '' : $peg); |
|
if (empty($rev)) |
$rev = $youngest; |
if (!$history) |
{ |
unset($vars['error']); |
$history = $svnrep->getLog($path, '', '', true, 2, ($path == '/') ? '' : $peg); |
} |
|
$history = $svnrep->getLog($path, $rev); |
$youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : false; |
|
if ($path{0} != "/") |
$ppath = "/".$path; |
else |
$ppath = $path; |
if (empty($rev)) |
{ |
$rev = $youngest; |
} |
|
$history = $svnrep->getLog($path, $rev, 1, false, 2, $peg); |
|
if ($path[0] != '/') |
{ |
$ppath = '/'.$path; |
} |
else |
{ |
$ppath = $path; |
} |
|
$prevrev = @$history->entries[1]->rev; |
|
$vars["repname"] = $rep->getDisplayName(); |
$vars["rev"] = $rev; |
$vars["path"] = $ppath; |
$vars["prevrev"] = $prevrev; |
$vars['path'] = str_replace('%2F', '/', rawurlencode($ppath)); |
$vars['safepath'] = escape($ppath); |
$vars['rev1'] = $rev; |
$vars['rev2'] = $prevrev; |
$vars['prevrev'] = $prevrev; |
|
$vars["rev1"] = $history->entries[0]->rev; |
$vars["rev2"] = $prevrev; |
if (isset($history->entries[0])) |
{ |
$vars['log'] = xml_entities($history->entries[0]->msg); |
$vars['date'] = $history->entries[0]->date; |
$vars['age'] = datetimeFormatDuration(time() - strtotime($history->entries[0]->date)); |
$vars['author'] = $history->entries[0]->author; |
$vars['rev'] = $vars['rev1'] = $history->entries[0]->rev; |
$vars['peg'] = $peg; |
} |
|
createDirLinks($rep, $ppath, $rev, $showchanged); |
createPathLinks($rep, $ppath, $passrev, $peg); |
$passRevString = createRevAndPegString($rev, $peg); |
|
$listing = array(); |
$passIgnoreWhitespace = ''; |
if ($ignoreWhitespace != $config->getIgnoreWhitespacesInDiff()) |
{ |
$passIgnoreWhitespace = '&ignorews='.($ignoreWhitespace ? '1' : '0'); |
} |
|
if ($prevrev) |
if ($rev != $youngest) |
{ |
$url = $config->getURL($rep, $path, "diff"); |
|
if (!$all) |
{ |
$vars["showalllink"] = "<a href=\"${url}rev=$rev&sc=$showchanged&all=1\">${lang["SHOWENTIREFILE"]}</a>"; |
$vars["showcompactlink"] = ""; |
} |
else |
{ |
$vars["showcompactlink"] = "<a href=\"${url}rev=$rev&sc=$showchanged&all=0\">${lang["SHOWCOMPACT"]}</a>"; |
$vars["showalllink"] = ""; |
} |
$vars['goyoungesturl'] = $config->getURL($rep, $path, 'diff').createRevAndPegString('', $peg).$passIgnoreWhitespace; |
$vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>'; |
} |
|
// Get the contents of the two files |
$newtname = tempnam("temp", ""); |
$new = $svnrep->getFileContents($history->entries[0]->path, $newtname, $history->entries[0]->rev, "", true); |
$revurl = $config->getURL($rep, $path, 'diff'); |
|
$oldtname = tempnam("temp", ""); |
$old = $svnrep->getFileContents($history->entries[1]->path, $oldtname, $history->entries[1]->rev, "", true); |
|
$ent = true; |
$extension = strrchr(basename($path), "."); |
if (($extension && isset($extEnscript[$extension]) && ('php' == $extEnscript[$extension])) || ($config->useEnscript)) |
$ent = false; |
if ($rev < $youngest) |
{ |
$history2 = $svnrep->getLog($path, $rev, $youngest, true, 2, $peg ? $peg : 'HEAD'); |
|
$file1cache = array(); |
if (isset($history2->entries[1])) |
{ |
$nextRev = $history2->entries[1]->rev; |
if ($nextRev != $youngest) |
{ |
$vars['nextrev'] = $nextRev; |
$vars['nextrevurl'] = $revurl.createRevAndPegString($nextRev, $peg).$passIgnoreWhitespace; |
} |
} |
|
if ($all) |
$context = 1; // Setting the context to 0 makes diff generate the wrong line numbers! |
unset($vars['error']); |
} |
|
// Open a pipe to the diff command with $context lines of context |
|
$cmd = quoteCommand($config->diff." --ignore-all-space -U $context $oldtname $newtname", false); |
|
if ($all) |
{ |
$ofile = fopen($oldtname, "r"); |
$nfile = fopen($newtname, "r"); |
} |
if (isset($history->entries[1])) |
{ |
$prevRev = $history->entries[1]->rev; |
$prevPath = $history->entries[1]->path; |
$vars['prevrev'] = $prevRev; |
$vars['prevrevurl'] = $revurl.createRevAndPegString($prevRev, $peg).$passIgnoreWhitespace; |
} |
|
if ($diff = popen($cmd, "r")) |
{ |
// Ignore the 3 header lines |
$line = fgets($diff); |
$line = fgets($diff); |
$vars['revurl'] = $config->getURL($rep, $path, 'revision').$passRevString; |
$vars['revlink'] = '<a href="'.$vars['revurl'].'">'.$lang['LASTMOD'].'</a>'; |
|
// Get the first real line |
$line = fgets($diff); |
|
$index = 0; |
$listing = array(); |
|
$curoline = 1; |
$curnline = 1; |
|
while (!feof($diff)) |
{ |
// Get the first line of this range |
sscanf($line, "@@ -%d", $oline); |
|
$line = substr($line, strpos($line, "+")); |
sscanf($line, "+%d", $nline); |
|
if ($all) |
{ |
while ($curoline < $oline || $curnline < $nline) |
{ |
$listing[$index]["rev1diffclass"] = "diff"; |
$listing[$index]["rev2diffclass"] = "diff"; |
|
if ($curoline < $oline) |
{ |
$nl = fgets($ofile); |
|
if ($ent) |
$line = replaceEntities(rtrim($nl), $rep); |
else |
$line = rtrim($nl); |
|
$listing[$index]["rev1line"] = hardspace($line); |
$vars['logurl'] = $config->getURL($rep, $path, 'log').$passRevString; |
$vars['loglink'] = '<a href="'.$vars['logurl'].'">'.$lang['VIEWLOG'].'</a>'; |
|
$curoline++; |
} |
else |
$listing[$index]["rev1line"] = " "; |
|
if ($curnline < $nline) |
{ |
$nl = fgets($nfile); |
$vars['filedetailurl'] = $config->getURL($rep, $path, 'file').$passRevString; |
$vars['filedetaillink'] = '<a href="'.$vars['filedetailurl'].'">'.$lang['FILEDETAIL'].'</a>'; |
|
if ($ent) |
$line = replaceEntities(rtrim($nl), $rep); |
else |
$line = rtrim($nl); |
|
$listing[$index]["rev2line"] = hardspace($line); |
$curnline++; |
} |
else |
$listing[$index]["rev2line"] = " "; |
|
$listing[$index]["rev1lineno"] = 0; |
$listing[$index]["rev2lineno"] = 0; |
$vars['blameurl'] = $config->getURL($rep, $path, 'blame').$passRevString; |
$vars['blamelink'] = '<a href="'.$vars['blameurl'].'">'.$lang['BLAME'].'</a>'; |
|
$index++; |
} |
} |
else |
{ |
// Output the line numbers |
$listing[$index]["rev1lineno"] = "$oline"; |
$listing[$index]["rev2lineno"] = "$nline"; |
$index++; |
} |
|
$fin = false; |
while (!feof($diff) && !$fin) |
{ |
$listing[$index]["rev1lineno"] = 0; |
$listing[$index]["rev2lineno"] = 0; |
if ($rep->isRssEnabled()) |
{ |
$vars['rssurl'] = $config->getURL($rep, $path, 'rss').createRevAndPegString('', $peg); |
$vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>'; |
} |
|
$line = fgets($diff); |
if (!strncmp($line, "@@", 2)) |
{ |
$fin = true; |
} |
else |
{ |
$mod = $line{0}; |
// Check for binary file type before diffing. |
$svnMimeType = $svnrep->getProperty($path, 'svn:mime-type', $rev); |
|
if ($ent) |
$line = replaceEntities(rtrim(substr($line, 1)), $rep); |
else |
$line = rtrim(substr($line, 1)); |
|
$listing[$index]["rev1line"] = hardspace($line); |
// If no previous revision exists, bail out before diffing |
if (!$rep->getIgnoreSvnMimeTypes() && preg_match('~application/*~', $svnMimeType)) |
{ |
$vars['warning'] = 'Cannot display diff of binary file. (svn:mime-type = '.$svnMimeType.')'; |
|
$text = hardspace($line); |
if ($text == "") $text = " "; |
|
switch ($mod) |
{ |
case "-": |
$listing[$index]["rev1diffclass"] = "diffdeleted"; |
$listing[$index]["rev2diffclass"] = "diff"; |
|
$listing[$index]["rev1line"] = $text; |
$listing[$index]["rev2line"] = " "; |
|
if ($all) |
{ |
fgets($ofile); |
$curoline++; |
} |
|
break; |
} |
else if (!$prevrev) |
{ |
$vars['noprev'] = 1; |
} |
else |
{ |
$diff = $config->getURL($rep, $path, 'diff').$passRevString; |
|
case "+": |
|
// Try to mark "changed" line sensibly |
if (!empty($listing[$index-1]) && empty($listing[$index-1]["rev1lineno"]) && @$listing[$index-1]["rev1diffclass"] == "diffdeleted" && @$listing[$index-1]["rev2diffclass"] == "diff") |
{ |
$i = $index - 1; |
while (!empty($listing[$i-1]) && empty($listing[$i-1]["rev1lineno"]) && $listing[$i-1]["rev1diffclass"] == "diffdeleted" && $listing[$i-1]["rev2diffclass"] == "diff") |
$i--; |
|
$listing[$i]["rev1diffclass"] = "diffchanged"; |
$listing[$i]["rev2diffclass"] = "diffchanged"; |
$listing[$i]["rev2line"] = $text; |
|
if ($all) |
{ |
fgets($nfile); |
$curnline++; |
} |
if ($all) |
{ |
$vars['showcompactlink'] = '<a href="'.$diff.$passIgnoreWhitespace.'">'.$lang['SHOWCOMPACT'].'</a>'; |
} |
else |
{ |
$vars['showalllink'] = '<a href="'.$diff.$passIgnoreWhitespace.'&all=1'.'">'.$lang['SHOWENTIREFILE'].'</a>'; |
} |
|
// Don't increment the current index count |
$index--; |
} |
else |
{ |
$listing[$index]["rev1diffclass"] = "diff"; |
$listing[$index]["rev2diffclass"] = "diffadded"; |
|
$listing[$index]["rev1line"] = " "; |
$listing[$index]["rev2line"] = $text; |
$passShowAll = ($all ? '&all=1' : ''); |
$toggleIgnoreWhitespace = ''; |
|
if ($all) |
{ |
fgets($nfile); |
$curnline++; |
} |
} |
break; |
|
default: |
$listing[$index]["rev1diffclass"] = "diff"; |
$listing[$index]["rev2diffclass"] = "diff"; |
|
$listing[$index]["rev1line"] = $text; |
$listing[$index]["rev2line"] = $text; |
|
if ($all) |
{ |
fgets($ofile); |
fgets($nfile); |
$curoline++; |
$curnline++; |
} |
if ($ignoreWhitespace == $config->getIgnoreWhitespacesInDiff()) |
{ |
$toggleIgnoreWhitespace = '&ignorews='.($ignoreWhitespace ? '0' : '1'); |
} |
|
break; |
} |
} |
|
if (!$fin) |
$index++; |
} |
} |
|
// Output the rest of the files |
if ($all) |
{ |
while (!feof($ofile) || !feof($nfile)) |
{ |
$listing[$index]["rev1diffclass"] = "diff"; |
$listing[$index]["rev2diffclass"] = "diff"; |
|
if ($ent) |
$line = replaceEntities(rtrim(fgets($ofile)), $rep); |
else |
$line = rtrim(fgets($ofile)); |
if ($ignoreWhitespace) |
{ |
$vars['regardwhitespacelink'] = '<a href="'.$diff.$passShowAll.$toggleIgnoreWhitespace.'">'.$lang['REGARDWHITESPACE'].'</a>'; |
} |
else |
{ |
$vars['ignorewhitespacelink'] = '<a href="'.$diff.$passShowAll.$toggleIgnoreWhitespace.'">'.$lang['IGNOREWHITESPACE'].'</a>'; |
} |
|
if (!feof($ofile)) |
$listing[$index]["rev1line"] = hardspace($line); |
else |
$listing[$index]["rev1line"] = " "; |
|
if ($ent) |
$line = replaceEntities(rtrim(fgets($nfile)), $rep); |
else |
$line = rtrim(fgets($nfile)); |
// Get the contents of the two files |
$newerFile = tempnamWithCheck($config->getTempDir(), ''); |
$newerFileHl = $newerFile.'highlight'; |
$normalNew = $svnrep->getFileContents($history->entries[0]->path, $newerFile, $history->entries[0]->rev, $peg, '', 'no'); |
$highlightedNew = $svnrep->getFileContents($history->entries[0]->path, $newerFileHl, $history->entries[0]->rev, $peg, '', 'line'); |
|
if (!feof($nfile)) |
$listing[$index]["rev2line"] = hardspace($line); |
else |
$listing[$index]["rev2line"] = " "; |
|
$listing[$index]["rev1lineno"] = 0; |
$listing[$index]["rev2lineno"] = 0; |
$olderFile = tempnamWithCheck($config->getTempDir(), ''); |
$olderFileHl = $olderFile.'highlight'; |
$normalOld = $svnrep->getFileContents($history->entries[0]->path, $olderFile, $history->entries[1]->rev, $peg, '', 'no'); |
$highlightedOld = $svnrep->getFileContents($history->entries[0]->path, $olderFileHl, $history->entries[1]->rev, $peg, '', 'line'); |
// TODO: Figured out why diffs across a move/rename are currently broken. |
|
$index++; |
} |
} |
|
pclose($diff); |
} |
|
if ($all) |
{ |
fclose($ofile); |
fclose($nfile); |
} |
$highlighted = ($highlightedNew && $highlightedOld); |
|
// Remove our temporary files |
unlink($oldtname); |
unlink($newtname); |
if ($highlighted) |
{ |
$listing = do_diff($all, $ignoreWhitespace, $highlighted, $newerFile, $olderFile, $newerFileHl, $olderFileHl); |
} |
else |
{ |
$listing = do_diff($all, $ignoreWhitespace, $highlighted, $newerFile, $olderFile, null, null); |
} |
|
// Remove our temporary files |
@unlink($newerFile); |
@unlink($olderFile); |
@unlink($newerFileHl); |
@unlink($olderFileHl); |
} |
else |
|
if (!$rep->hasReadAccess($path, false)) |
{ |
$vars["noprev"] = 1; |
$vars['error'] = $lang['NOACCESS']; |
sendHeaderForbidden(); |
} |
|
$vars["version"] = $version; |
|
if (!$rep->hasReadAccess($path, false)) |
$vars["noaccess"] = true; |
|
parseTemplate($rep->getTemplatePath()."header.tmpl", $vars, $listing); |
parseTemplate($rep->getTemplatePath()."diff.tmpl", $vars, $listing); |
parseTemplate($rep->getTemplatePath()."footer.tmpl", $vars, $listing); |
|
?> |
renderTemplate('diff'); |