Rev 185 Rev 4988
1 <?php 1 <?php
2 # vim:et:ts=3:sts=3:sw=3:fdm=marker: -  
3   -  
4 // WebSVN - Subversion repository viewing via the web using PHP 2 // WebSVN - Subversion repository viewing via the web using PHP
5 // Copyright © 2004-2006 Tim Armes, Matt Sicker 3 // Copyright (C) 2004-2006 Tim Armes
6 // 4 //
7 // This program is free software; you can redistribute it and/or modify 5 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by 6 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or 7 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version. 8 // (at your option) any later version.
11 // 9 //
12 // This program is distributed in the hope that it will be useful, 10 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details. 13 // GNU General Public License for more details.
16 // 14 //
17 // You should have received a copy of the GNU General Public License 15 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software 16 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // 18 //
21 // -- 19 // --
22 // 20 //
23 // diff.php 21 // diff.php
24 // 22 //
25 // Show the differences between 2 revisions of a file. 23 // Show the differences between 2 revisions of a file.
26 // 24 //
27   25  
28 require_once("include/setup.inc"); 26 require_once 'include/setup.php';
29 require_once("include/svnlook.inc"); 27 require_once 'include/svnlook.php';
30 require_once("include/utils.inc"); 28 require_once 'include/utils.php';
31 require_once("include/template.inc"); 29 require_once 'include/template.php';
-   30  
-   31 require_once 'include/diff_inc.php';
32   32  
33 $context = 5; 33 $vars['action'] = $lang['DIFF'];
-   34 $all = (@$_REQUEST['all'] == 1);
-   35 $ignoreWhitespace = $config->getIgnoreWhitespacesInDiff();
34   36  
35 $vars["action"] = $lang["DIFF"]; 37 if (array_key_exists('ignorews', $_REQUEST))
-   38 {
36 $all = (@$_REQUEST["all"] == 1)?1:0; 39 $ignoreWhitespace = (bool)$_REQUEST['ignorews'];
-   40 }
37   41  
38 // Make sure that we have a repository 42 // Make sure that we have a repository
39 if (!isset($rep)) 43 if (!$rep)
40 { 44 {
41 echo $lang["NOREP"]; 45 renderTemplate404('diff','NOREP');
42 exit; -  
43 } 46 }
44   47  
45 $svnrep = new SVNRepository($rep); 48 $svnrep = new SVNRepository($rep);
46   49  
47 // If there's no revision info, go to the lastest revision for this path 50 // If there's no revision info, go to the lastest revision for this path
48 $history = $svnrep->getLog($path, "", "", true); 51 $history = $svnrep->getLog($path, 'HEAD', 1, true, 2, ($path == '/') ? '' : $peg);
49 $youngest = $history->entries[0]->rev; -  
50   52  
51 if (empty($rev)) 53 if (!$history)
-   54 {
52 $rev = $youngest; 55 unset($vars['error']);
-   56 $history = $svnrep->getLog($path, '', '', true, 2, ($path == '/') ? '' : $peg);
-   57 }
53   58  
54 $history = $svnrep->getLog($path, $rev); 59 $youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : false;
55   60  
-   61 if (empty($rev))
-   62 {
-   63 $rev = $youngest;
-   64 }
-   65  
-   66 $history = $svnrep->getLog($path, $rev, 1, false, 2, $peg);
-   67  
56 if ($path{0} != "/") 68 if ($path[0] != '/')
-   69 {
57 $ppath = "/".$path; 70 $ppath = '/'.$path;
-   71 }
58 else 72 else
-   73 {
59 $ppath = $path; 74 $ppath = $path;
-   75 }
60   76  
61 $prevrev = @$history->entries[1]->rev; 77 $prevrev = @$history->entries[1]->rev;
62   78  
63 $vars["repname"] = $rep->getDisplayName(); 79 $vars['path'] = str_replace('%2F', '/', rawurlencode($ppath));
64 $vars["rev"] = $rev; 80 $vars['safepath'] = escape($ppath);
65 $vars["path"] = $ppath; 81 $vars['rev1'] = $rev;
66 $vars["prevrev"] = $prevrev; 82 $vars['rev2'] = $prevrev;
67   -  
68 $vars["rev1"] = $history->entries[0]->rev; -  
69 $vars["rev2"] = $prevrev; 83 $vars['prevrev'] = $prevrev;
70   -  
71 createDirLinks($rep, $ppath, $rev, $showchanged); -  
72   -  
73 $listing = array(); -  
74   84  
75 if ($prevrev) 85 if (isset($history->entries[0]))
76 { 86 {
77 $url = $config->getURL($rep, $path, "diff"); 87 $vars['log'] = xml_entities($history->entries[0]->msg);
78 -  
79 if (!$all) -  
80 { -  
81 $vars["showalllink"] = "<a href=\"${url}rev=$rev&amp;sc=$showchanged&amp;all=1\">${lang["SHOWENTIREFILE"]}</a>"; -  
82 $vars["showcompactlink"] = ""; -  
83 } -  
84 else -  
85 { -  
86 $vars["showcompactlink"] = "<a href=\"${url}rev=$rev&amp;sc=$showchanged&amp;all=0\">${lang["SHOWCOMPACT"]}</a>"; -  
87 $vars["showalllink"] = ""; -  
88 } -  
89   -  
90 // Get the contents of the two files -  
91 $newtname = tempnam("temp", ""); -  
92 $new = $svnrep->getFileContents($history->entries[0]->path, $newtname, $history->entries[0]->rev, "", true); -  
93   -  
94 $oldtname = tempnam("temp", ""); 88 $vars['date'] = $history->entries[0]->date;
95 $old = $svnrep->getFileContents($history->entries[1]->path, $oldtname, $history->entries[1]->rev, "", true); 89 $vars['age'] = datetimeFormatDuration(time() - strtotime($history->entries[0]->date));
96 -  
97 $ent = true; -  
98 $extension = strrchr(basename($path), "."); 90 $vars['author'] = $history->entries[0]->author;
99 if (($extension && isset($extEnscript[$extension]) && ('php' == $extEnscript[$extension])) || ($config->useEnscript)) -  
100 $ent = false; -  
101   -  
102 $file1cache = array(); -  
103   -  
104 if ($all) -  
105 $context = 1; // Setting the context to 0 makes diff generate the wrong line numbers! -  
106   -  
107 // Open a pipe to the diff command with $context lines of context -  
108 -  
109 $cmd = quoteCommand($config->diff." --ignore-all-space -U $context $oldtname $newtname", false); -  
110 -  
111 if ($all) -  
112 { -  
113 $ofile = fopen($oldtname, "r"); -  
114 $nfile = fopen($newtname, "r"); -  
115 } -  
116   -  
117 if ($diff = popen($cmd, "r")) -  
118 { -  
119 // Ignore the 3 header lines -  
120 $line = fgets($diff); -  
121 $line = fgets($diff); -  
122   -  
123 // Get the first real line -  
124 $line = fgets($diff); -  
125 -  
126 $index = 0; -  
127 $listing = array(); -  
128 -  
129 $curoline = 1; -  
130 $curnline = 1; -  
131 -  
132 while (!feof($diff)) -  
133 { -  
134 // Get the first line of this range -  
135 sscanf($line, "@@ -%d", $oline); -  
136 -  
137 $line = substr($line, strpos($line, "+")); 91 $vars['rev'] = $vars['rev1'] = $history->entries[0]->rev;
138 sscanf($line, "+%d", $nline); -  
139 -  
140 if ($all) -  
141 { -  
142 while ($curoline < $oline || $curnline < $nline) -  
143 { -  
144 $listing[$index]["rev1diffclass"] = "diff"; -  
145 $listing[$index]["rev2diffclass"] = "diff"; -  
146 -  
147 if ($curoline < $oline) -  
148 { -  
149 $nl = fgets($ofile); -  
150 -  
151 if ($ent) -  
152 $line = replaceEntities(rtrim($nl), $rep); -  
153 else -  
154 $line = rtrim($nl); -  
155 -  
156 $listing[$index]["rev1line"] = hardspace($line); -  
157   -  
158 $curoline++; -  
159 } -  
160 else -  
161 $listing[$index]["rev1line"] = "&nbsp;"; -  
162 -  
163 if ($curnline < $nline) -  
164 { -  
165 $nl = fgets($nfile); -  
166   -  
167 if ($ent) -  
168 $line = replaceEntities(rtrim($nl), $rep); -  
169 else -  
170 $line = rtrim($nl); -  
171 -  
172 $listing[$index]["rev2line"] = hardspace($line); -  
173 $curnline++; -  
174 } -  
175 else -  
176 $listing[$index]["rev2line"] = "&nbsp;"; -  
177 -  
178 $listing[$index]["rev1lineno"] = 0; -  
179 $listing[$index]["rev2lineno"] = 0; -  
180   -  
181 $index++; -  
182 } -  
183 } -  
184 else -  
185 { -  
186 // Output the line numbers -  
187 $listing[$index]["rev1lineno"] = "$oline"; -  
188 $listing[$index]["rev2lineno"] = "$nline"; -  
189 $index++; -  
190 } -  
191 -  
192 $fin = false; -  
193 while (!feof($diff) && !$fin) -  
194 { -  
195 $listing[$index]["rev1lineno"] = 0; -  
196 $listing[$index]["rev2lineno"] = 0; -  
197   -  
198 $line = fgets($diff); -  
199 if (!strncmp($line, "@@", 2)) -  
200 { -  
201 $fin = true; 92 $vars['peg'] = $peg;
202 } -  
203 else -  
204 { -  
205 $mod = $line{0}; -  
206   -  
207 if ($ent) -  
208 $line = replaceEntities(rtrim(substr($line, 1)), $rep); -  
209 else -  
210 $line = rtrim(substr($line, 1)); -  
211 -  
212 $listing[$index]["rev1line"] = hardspace($line); -  
213   -  
214 $text = hardspace($line); -  
215 if ($text == "") $text = "&nbsp;"; -  
216 -  
217 switch ($mod) -  
218 { -  
219 case "-": -  
220 $listing[$index]["rev1diffclass"] = "diffdeleted"; -  
221 $listing[$index]["rev2diffclass"] = "diff"; -  
222 -  
223 $listing[$index]["rev1line"] = $text; -  
224 $listing[$index]["rev2line"] = "&nbsp;"; -  
225 -  
226 if ($all) -  
227 { -  
228 fgets($ofile); -  
229 $curoline++; -  
230 } -  
231 -  
232 break; -  
233   -  
234 case "+": -  
235 -  
236 // Try to mark "changed" line sensibly -  
237 if (!empty($listing[$index-1]) && empty($listing[$index-1]["rev1lineno"]) && @$listing[$index-1]["rev1diffclass"] == "diffdeleted" && @$listing[$index-1]["rev2diffclass"] == "diff") -  
238 { -  
239 $i = $index - 1; -  
240 while (!empty($listing[$i-1]) && empty($listing[$i-1]["rev1lineno"]) && $listing[$i-1]["rev1diffclass"] == "diffdeleted" && $listing[$i-1]["rev2diffclass"] == "diff") -  
241 $i--; -  
242 -  
243 $listing[$i]["rev1diffclass"] = "diffchanged"; -  
244 $listing[$i]["rev2diffclass"] = "diffchanged"; -  
245 $listing[$i]["rev2line"] = $text; -  
246 -  
247 if ($all) -  
248 { -  
249 fgets($nfile); -  
250 $curnline++; -  
251 } -  
252   -  
253 // Don't increment the current index count -  
254 $index--; -  
255 } -  
256 else -  
257 { -  
258 $listing[$index]["rev1diffclass"] = "diff"; -  
259 $listing[$index]["rev2diffclass"] = "diffadded"; -  
260 -  
261 $listing[$index]["rev1line"] = "&nbsp;"; -  
262 $listing[$index]["rev2line"] = $text; -  
263   -  
264 if ($all) -  
265 { -  
266 fgets($nfile); -  
267 $curnline++; -  
268 } -  
269 } -  
270 break; -  
271 -  
272 default: -  
273 $listing[$index]["rev1diffclass"] = "diff"; -  
274 $listing[$index]["rev2diffclass"] = "diff"; -  
275 -  
276 $listing[$index]["rev1line"] = $text; -  
277 $listing[$index]["rev2line"] = $text; -  
278 -  
279 if ($all) -  
280 { -  
281 fgets($ofile); -  
282 fgets($nfile); -  
283 $curoline++; -  
284 $curnline++; -  
285 } -  
286   -  
287 break; -  
288 } -  
289 } -  
290 -  
291 if (!$fin) -  
292 $index++; -  
293 } -  
294 } -  
295 -  
296 // Output the rest of the files -  
297 if ($all) -  
298 { -  
299 while (!feof($ofile) || !feof($nfile)) -  
300 { -  
301 $listing[$index]["rev1diffclass"] = "diff"; -  
302 $listing[$index]["rev2diffclass"] = "diff"; -  
303 -  
304 if ($ent) -  
305 $line = replaceEntities(rtrim(fgets($ofile)), $rep); -  
306 else -  
307 $line = rtrim(fgets($ofile)); -  
308   -  
309 if (!feof($ofile)) -  
310 $listing[$index]["rev1line"] = hardspace($line); -  
311 else -  
312 $listing[$index]["rev1line"] = "&nbsp;"; -  
313 -  
314 if ($ent) -  
315 $line = replaceEntities(rtrim(fgets($nfile)), $rep); -  
316 else -  
317 $line = rtrim(fgets($nfile)); -  
318   -  
319 if (!feof($nfile)) -  
320 $listing[$index]["rev2line"] = hardspace($line); -  
321 else -  
322 $listing[$index]["rev2line"] = "&nbsp;"; -  
323 -  
324 $listing[$index]["rev1lineno"] = 0; -  
325 $listing[$index]["rev2lineno"] = 0; -  
326   -  
327 $index++; -  
328 } -  
329 } -  
330 -  
331 pclose($diff); -  
332 } -  
333 -  
334 if ($all) -  
335 { -  
336 fclose($ofile); -  
337 fclose($nfile); -  
338 } -  
339   -  
340 // Remove our temporary files -  
341 unlink($oldtname); -  
342 unlink($newtname); -  
343 } 93 }
-   94  
-   95 createPathLinks($rep, $ppath, $passrev, $peg);
-   96 $passRevString = createRevAndPegString($rev, $peg);
344 else 97  
-   98 $passIgnoreWhitespace = '';
-   99 if ($ignoreWhitespace != $config->getIgnoreWhitespacesInDiff())
345 { 100 {
346 $vars["noprev"] = 1; 101 $passIgnoreWhitespace = '&amp;ignorews='.($ignoreWhitespace ? '1' : '0');
347 } 102 }
348   103  
-   104 if ($rev != $youngest)
-   105 {
-   106 $vars['goyoungesturl'] = $config->getURL($rep, $path, 'diff').createRevAndPegString('', $peg).$passIgnoreWhitespace;
-   107 $vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>';
-   108 }
-   109  
-   110 $revurl = $config->getURL($rep, $path, 'diff');
-   111  
-   112 if ($rev < $youngest)
-   113 {
-   114 $history2 = $svnrep->getLog($path, $rev, $youngest, true, 2, $peg ? $peg : 'HEAD');
-   115  
-   116 if (isset($history2->entries[1]))
-   117 {
-   118 $nextRev = $history2->entries[1]->rev;
-   119 if ($nextRev != $youngest)
-   120 {
349 $vars["version"] = $version; 121 $vars['nextrev'] = $nextRev;
-   122 $vars['nextrevurl'] = $revurl.createRevAndPegString($nextRev, $peg).$passIgnoreWhitespace;
-   123 }
-   124 }
350   125  
-   126 unset($vars['error']);
-   127 }
-   128  
-   129 if (isset($history->entries[1]))
-   130 {
-   131 $prevRev = $history->entries[1]->rev;
-   132 $prevPath = $history->entries[1]->path;
-   133 $vars['prevrev'] = $prevRev;
-   134 $vars['prevrevurl'] = $revurl.createRevAndPegString($prevRev, $peg).$passIgnoreWhitespace;
-   135 }
-   136  
-   137 $vars['revurl'] = $config->getURL($rep, $path, 'revision').$passRevString;
-   138 $vars['revlink'] = '<a href="'.$vars['revurl'].'">'.$lang['LASTMOD'].'</a>';
-   139  
-   140 $vars['logurl'] = $config->getURL($rep, $path, 'log').$passRevString;
-   141 $vars['loglink'] = '<a href="'.$vars['logurl'].'">'.$lang['VIEWLOG'].'</a>';
-   142  
-   143 $vars['filedetailurl'] = $config->getURL($rep, $path, 'file').$passRevString;
-   144 $vars['filedetaillink'] = '<a href="'.$vars['filedetailurl'].'">'.$lang['FILEDETAIL'].'</a>';
-   145  
-   146 $vars['blameurl'] = $config->getURL($rep, $path, 'blame').$passRevString;
-   147 $vars['blamelink'] = '<a href="'.$vars['blameurl'].'">'.$lang['BLAME'].'</a>';
-   148  
-   149 if ($rep->isRssEnabled())
-   150 {
-   151 $vars['rssurl'] = $config->getURL($rep, $path, 'rss').createRevAndPegString('', $peg);
-   152 $vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>';
-   153 }
-   154  
-   155 // Check for binary file type before diffing.
-   156 $svnMimeType = $svnrep->getProperty($path, 'svn:mime-type', $rev);
-   157  
-   158 // If no previous revision exists, bail out before diffing
-   159 if (!$rep->getIgnoreSvnMimeTypes() && preg_match('~application/*~', $svnMimeType))
-   160 {
-   161 $vars['warning'] = 'Cannot display diff of binary file. (svn:mime-type = '.$svnMimeType.')';
-   162  
-   163 }
-   164 else if (!$prevrev)
-   165 {
-   166 $vars['noprev'] = 1;
-   167 }
-   168 else
-   169 {
-   170 $diff = $config->getURL($rep, $path, 'diff').$passRevString;
-   171  
-   172 if ($all)
-   173 {
-   174 $vars['showcompactlink'] = '<a href="'.$diff.$passIgnoreWhitespace.'">'.$lang['SHOWCOMPACT'].'</a>';
-   175 }
-   176 else
-   177 {
-   178 $vars['showalllink'] = '<a href="'.$diff.$passIgnoreWhitespace.'&amp;all=1'.'">'.$lang['SHOWENTIREFILE'].'</a>';
-   179 }
-   180  
-   181 $passShowAll = ($all ? '&amp;all=1' : '');
-   182 $toggleIgnoreWhitespace = '';
-   183  
-   184 if ($ignoreWhitespace == $config->getIgnoreWhitespacesInDiff())
-   185 {
-   186 $toggleIgnoreWhitespace = '&amp;ignorews='.($ignoreWhitespace ? '0' : '1');
-   187 }
-   188  
-   189 if ($ignoreWhitespace)
-   190 {
-   191 $vars['regardwhitespacelink'] = '<a href="'.$diff.$passShowAll.$toggleIgnoreWhitespace.'">'.$lang['REGARDWHITESPACE'].'</a>';
-   192 }
-   193 else
-   194 {
-   195 $vars['ignorewhitespacelink'] = '<a href="'.$diff.$passShowAll.$toggleIgnoreWhitespace.'">'.$lang['IGNOREWHITESPACE'].'</a>';
-   196 }
-   197  
-   198 // Get the contents of the two files
-   199 $newerFile = tempnamWithCheck($config->getTempDir(), '');
-   200 $newerFileHl = $newerFile.'highlight';
-   201 $normalNew = $svnrep->getFileContents($history->entries[0]->path, $newerFile, $history->entries[0]->rev, $peg, '', 'no');
-   202 $highlightedNew = $svnrep->getFileContents($history->entries[0]->path, $newerFileHl, $history->entries[0]->rev, $peg, '', 'line');
-   203  
-   204 $olderFile = tempnamWithCheck($config->getTempDir(), '');
-   205 $olderFileHl = $olderFile.'highlight';
-   206 $normalOld = $svnrep->getFileContents($history->entries[0]->path, $olderFile, $history->entries[1]->rev, $peg, '', 'no');
-   207 $highlightedOld = $svnrep->getFileContents($history->entries[0]->path, $olderFileHl, $history->entries[1]->rev, $peg, '', 'line');
-   208 // TODO: Figured out why diffs across a move/rename are currently broken.
-   209  
-   210 $highlighted = ($highlightedNew && $highlightedOld);
-   211  
-   212 if ($highlighted)
-   213 {
-   214 $listing = do_diff($all, $ignoreWhitespace, $highlighted, $newerFile, $olderFile, $newerFileHl, $olderFileHl);
-   215 }
-   216 else
-   217 {
-   218 $listing = do_diff($all, $ignoreWhitespace, $highlighted, $newerFile, $olderFile, null, null);
-   219 }
-   220  
-   221 // Remove our temporary files
-   222 @unlink($newerFile);
-   223 @unlink($olderFile);
-   224 @unlink($newerFileHl);
-   225 @unlink($olderFileHl);
-   226 }
-   227  
351 if (!$rep->hasReadAccess($path, false)) 228 if (!$rep->hasReadAccess($path, false))
-   229 {
352 $vars["noaccess"] = true; 230 $vars['error'] = $lang['NOACCESS'];
-   231 sendHeaderForbidden();
-   232 }
353   233  
354 parseTemplate($rep->getTemplatePath()."header.tmpl", $vars, $listing); -  
355 parseTemplate($rep->getTemplatePath()."diff.tmpl", $vars, $listing); 234 renderTemplate('diff');
356 parseTemplate($rep->getTemplatePath()."footer.tmpl", $vars, $listing); -  
357 -  
358 ?> -