Rev 185 Rev 4988
Line 1... Line 1...
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.
Line 23... Line 21...
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   -  
51 if (empty($rev)) -  
52 $rev = $youngest; -  
53   -  
54 $history = $svnrep->getLog($path, $rev); -  
55   -  
56 if ($path{0} != "/") -  
57 $ppath = "/".$path; -  
58 else -  
59 $ppath = $path; -  
60   -  
61 $prevrev = @$history->entries[1]->rev; -  
62   52  
63 $vars["repname"] = $rep->getDisplayName(); -  
64 $vars["rev"] = $rev; 53 if (!$history)
65 $vars["path"] = $ppath; -  
66 $vars["prevrev"] = $prevrev; -  
67   54 {
68 $vars["rev1"] = $history->entries[0]->rev; 55 unset($vars['error']);
69 $vars["rev2"] = $prevrev; 56 $history = $svnrep->getLog($path, '', '', true, 2, ($path == '/') ? '' : $peg);
70   57 }
71 createDirLinks($rep, $ppath, $rev, $showchanged); -  
72   58  
73 $listing = array(); 59 $youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : false;
74   60  
75 if ($prevrev) 61 if (empty($rev))
76 { 62 {
77 $url = $config->getURL($rep, $path, "diff"); 63 $rev = $youngest;
-   64 }
78 65  
-   66 $history = $svnrep->getLog($path, $rev, 1, false, 2, $peg);
-   67  
79 if (!$all) 68 if ($path[0] != '/')
80 { 69 {
81 $vars["showalllink"] = "<a href=\"${url}rev=$rev&amp;sc=$showchanged&amp;all=1\">${lang["SHOWENTIREFILE"]}</a>"; -  
82 $vars["showcompactlink"] = ""; 70 $ppath = '/'.$path;
83 } 71 }
84 else 72 else
85 { 73 {
86 $vars["showcompactlink"] = "<a href=\"${url}rev=$rev&amp;sc=$showchanged&amp;all=0\">${lang["SHOWCOMPACT"]}</a>"; -  
87 $vars["showalllink"] = ""; 74 $ppath = $path;
88 } 75 }
89   76  
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", ""); -  
95 $old = $svnrep->getFileContents($history->entries[1]->path, $oldtname, $history->entries[1]->rev, "", true); -  
96 -  
97 $ent = true; -  
98 $extension = strrchr(basename($path), "."); 77 $prevrev = @$history->entries[1]->rev;
99 if (($extension && isset($extEnscript[$extension]) && ('php' == $extEnscript[$extension])) || ($config->useEnscript)) -  
100 $ent = false; -  
101   -  
102 $file1cache = array(); -  
103   78  
-   79 $vars['path'] = str_replace('%2F', '/', rawurlencode($ppath));
-   80 $vars['safepath'] = escape($ppath);
104 if ($all) 81 $vars['rev1'] = $rev;
-   82 $vars['rev2'] = $prevrev;
105 $context = 1; // Setting the context to 0 makes diff generate the wrong line numbers! 83 $vars['prevrev'] = $prevrev;
106   84  
-   85 if (isset($history->entries[0]))
-   86 {
-   87 $vars['log'] = xml_entities($history->entries[0]->msg);
-   88 $vars['date'] = $history->entries[0]->date;
107 // Open a pipe to the diff command with $context lines of context 89 $vars['age'] = datetimeFormatDuration(time() - strtotime($history->entries[0]->date));
-   90 $vars['author'] = $history->entries[0]->author;
-   91 $vars['rev'] = $vars['rev1'] = $history->entries[0]->rev;
-   92 $vars['peg'] = $peg;
-   93 }
108 94  
-   95 createPathLinks($rep, $ppath, $passrev, $peg);
109 $cmd = quoteCommand($config->diff." --ignore-all-space -U $context $oldtname $newtname", false); 96 $passRevString = createRevAndPegString($rev, $peg);
110 97  
111 if ($all) 98 $passIgnoreWhitespace = '';
-   99 if ($ignoreWhitespace != $config->getIgnoreWhitespacesInDiff())
112 { 100 {
113 $ofile = fopen($oldtname, "r"); -  
114 $nfile = fopen($newtname, "r"); 101 $passIgnoreWhitespace = '&amp;ignorews='.($ignoreWhitespace ? '1' : '0');
115 } 102 }
116   103  
117 if ($diff = popen($cmd, "r")) 104 if ($rev != $youngest)
118 { 105 {
119 // Ignore the 3 header lines 106 $vars['goyoungesturl'] = $config->getURL($rep, $path, 'diff').createRevAndPegString('', $peg).$passIgnoreWhitespace;
120 $line = fgets($diff); -  
121 $line = fgets($diff); 107 $vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>';
122   108 }
123 // Get the first real line -  
124 $line = fgets($diff); -  
125 -  
126 $index = 0; -  
127 $listing = array(); -  
128 109  
129 $curoline = 1; -  
130 $curnline = 1; 110 $revurl = $config->getURL($rep, $path, 'diff');
131 111  
132 while (!feof($diff)) 112 if ($rev < $youngest)
133 { 113 {
134 // Get the first line of this range -  
135 sscanf($line, "@@ -%d", $oline); -  
136 -  
137 $line = substr($line, strpos($line, "+")); 114 $history2 = $svnrep->getLog($path, $rev, $youngest, true, 2, $peg ? $peg : 'HEAD');
138 sscanf($line, "+%d", $nline); -  
139 115  
140 if ($all) 116 if (isset($history2->entries[1]))
141 { 117 {
142 while ($curoline < $oline || $curnline < $nline) 118 $nextRev = $history2->entries[1]->rev;
-   119 if ($nextRev != $youngest)
143 { 120 {
144 $listing[$index]["rev1diffclass"] = "diff"; -  
145 $listing[$index]["rev2diffclass"] = "diff"; -  
146 -  
147 if ($curoline < $oline) -  
148 { -  
149 $nl = fgets($ofile); 121 $vars['nextrev'] = $nextRev;
150 -  
151 if ($ent) -  
152 $line = replaceEntities(rtrim($nl), $rep); 122 $vars['nextrevurl'] = $revurl.createRevAndPegString($nextRev, $peg).$passIgnoreWhitespace;
153 else -  
154 $line = rtrim($nl); -  
155 -  
156 $listing[$index]["rev1line"] = hardspace($line); -  
157   -  
158 $curoline++; -  
159 } 123 }
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 } 124 }
175 else -  
176 $listing[$index]["rev2line"] = "&nbsp;"; -  
177 125  
178 $listing[$index]["rev1lineno"] = 0; -  
179 $listing[$index]["rev2lineno"] = 0; -  
180   -  
181 $index++; 126 unset($vars['error']);
182 } -  
183 } -  
184 else -  
185 { -  
186 // Output the line numbers -  
187 $listing[$index]["rev1lineno"] = "$oline"; -  
188 $listing[$index]["rev2lineno"] = "$nline"; -  
189 $index++; -  
190 } 127 }
191 128  
192 $fin = false; -  
193 while (!feof($diff) && !$fin) -  
194 { -  
195 $listing[$index]["rev1lineno"] = 0; -  
196 $listing[$index]["rev2lineno"] = 0; -  
197   -  
198 $line = fgets($diff); 129 if (isset($history->entries[1]))
199 if (!strncmp($line, "@@", 2)) -  
200 { 130 {
-   131 $prevRev = $history->entries[1]->rev;
-   132 $prevPath = $history->entries[1]->path;
201 $fin = true; 133 $vars['prevrev'] = $prevRev;
-   134 $vars['prevrevurl'] = $revurl.createRevAndPegString($prevRev, $peg).$passIgnoreWhitespace;
202 } 135 }
203 else -  
204 { -  
205 $mod = $line{0}; -  
206   136  
207 if ($ent) -  
208 $line = replaceEntities(rtrim(substr($line, 1)), $rep); 137 $vars['revurl'] = $config->getURL($rep, $path, 'revision').$passRevString;
209 else -  
210 $line = rtrim(substr($line, 1)); 138 $vars['revlink'] = '<a href="'.$vars['revurl'].'">'.$lang['LASTMOD'].'</a>';
211 139  
212 $listing[$index]["rev1line"] = hardspace($line); 140 $vars['logurl'] = $config->getURL($rep, $path, 'log').$passRevString;
-   141 $vars['loglink'] = '<a href="'.$vars['logurl'].'">'.$lang['VIEWLOG'].'</a>';
213   142  
214 $text = hardspace($line); 143 $vars['filedetailurl'] = $config->getURL($rep, $path, 'file').$passRevString;
215 if ($text == "") $text = "&nbsp;"; 144 $vars['filedetaillink'] = '<a href="'.$vars['filedetailurl'].'">'.$lang['FILEDETAIL'].'</a>';
216 145  
217 switch ($mod) -  
218 { -  
219 case "-": -  
220 $listing[$index]["rev1diffclass"] = "diffdeleted"; 146 $vars['blameurl'] = $config->getURL($rep, $path, 'blame').$passRevString;
221 $listing[$index]["rev2diffclass"] = "diff"; -  
222 -  
223 $listing[$index]["rev1line"] = $text; -  
224 $listing[$index]["rev2line"] = "&nbsp;"; 147 $vars['blamelink'] = '<a href="'.$vars['blameurl'].'">'.$lang['BLAME'].'</a>';
225 148  
226 if ($all) 149 if ($rep->isRssEnabled())
227 { 150 {
228 fgets($ofile); 151 $vars['rssurl'] = $config->getURL($rep, $path, 'rss').createRevAndPegString('', $peg);
229 $curoline++; 152 $vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>';
230 } 153 }
231 154  
232 break; 155 // Check for binary file type before diffing.
-   156 $svnMimeType = $svnrep->getProperty($path, 'svn:mime-type', $rev);
233   157  
234 case "+": -  
235 -  
236 // Try to mark "changed" line sensibly 158 // If no previous revision exists, bail out before diffing
237 if (!empty($listing[$index-1]) && empty($listing[$index-1]["rev1lineno"]) && @$listing[$index-1]["rev1diffclass"] == "diffdeleted" && @$listing[$index-1]["rev2diffclass"] == "diff") 159 if (!$rep->getIgnoreSvnMimeTypes() && preg_match('~application/*~', $svnMimeType))
238 { 160 {
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"; 161 $vars['warning'] = 'Cannot display diff of binary file. (svn:mime-type = '.$svnMimeType.')';
245 $listing[$i]["rev2line"] = $text; -  
246 162  
247 if ($all) -  
248 { -  
249 fgets($nfile); -  
250 $curnline++; -  
251 } 163 }
-   164 else if (!$prevrev)
252   165 {
253 // Don't increment the current index count -  
254 $index--; 166 $vars['noprev'] = 1;
255 } 167 }
256 else 168 else
257 { 169 {
258 $listing[$index]["rev1diffclass"] = "diff"; 170 $diff = $config->getURL($rep, $path, 'diff').$passRevString;
259 $listing[$index]["rev2diffclass"] = "diffadded"; -  
260 -  
261 $listing[$index]["rev1line"] = "&nbsp;"; -  
262 $listing[$index]["rev2line"] = $text; -  
263   171  
264 if ($all) 172 if ($all)
265 { 173 {
266 fgets($nfile); 174 $vars['showcompactlink'] = '<a href="'.$diff.$passIgnoreWhitespace.'">'.$lang['SHOWCOMPACT'].'</a>';
267 $curnline++; -  
268 } 175 }
269 } -  
270 break; -  
271 -  
272 default: -  
273 $listing[$index]["rev1diffclass"] = "diff"; -  
274 $listing[$index]["rev2diffclass"] = "diff"; -  
275 176 else
276 $listing[$index]["rev1line"] = $text; -  
277 $listing[$index]["rev2line"] = $text; -  
278 -  
279 if ($all) -  
280 { 177 {
281 fgets($ofile); -  
282 fgets($nfile); 178 $vars['showalllink'] = '<a href="'.$diff.$passIgnoreWhitespace.'&amp;all=1'.'">'.$lang['SHOWENTIREFILE'].'</a>';
283 $curoline++; -  
284 $curnline++; -  
285 } 179 }
286   180  
287 break; 181 $passShowAll = ($all ? '&amp;all=1' : '');
288 } 182 $toggleIgnoreWhitespace = '';
289 } -  
290 183  
291 if (!$fin) -  
292 $index++; 184 if ($ignoreWhitespace == $config->getIgnoreWhitespacesInDiff())
293 } 185 {
-   186 $toggleIgnoreWhitespace = '&amp;ignorews='.($ignoreWhitespace ? '0' : '1');
294 } 187 }
295 188  
296 // Output the rest of the files 189 if ($ignoreWhitespace)
297 if ($all) -  
298 { 190 {
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); 191 $vars['regardwhitespacelink'] = '<a href="'.$diff.$passShowAll.$toggleIgnoreWhitespace.'">'.$lang['REGARDWHITESPACE'].'</a>';
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   192 }
319 if (!feof($nfile)) -  
320 $listing[$index]["rev2line"] = hardspace($line); -  
321 else 193 else
-   194 {
322 $listing[$index]["rev2line"] = "&nbsp;"; 195 $vars['ignorewhitespacelink'] = '<a href="'.$diff.$passShowAll.$toggleIgnoreWhitespace.'">'.$lang['IGNOREWHITESPACE'].'</a>';
-   196 }
323 197  
324 $listing[$index]["rev1lineno"] = 0; 198 // Get the contents of the two files
-   199 $newerFile = tempnamWithCheck($config->getTempDir(), '');
325 $listing[$index]["rev2lineno"] = 0; 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');
326   203  
-   204 $olderFile = tempnamWithCheck($config->getTempDir(), '');
327 $index++; 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');
328 } 208 // TODO: Figured out why diffs across a move/rename are currently broken.
329 } -  
330 209  
331 pclose($diff); 210 $highlighted = ($highlightedNew && $highlightedOld);
332 } -  
333 211  
334 if ($all) 212 if ($highlighted)
335 { 213 {
336 fclose($ofile); -  
337 fclose($nfile); -  
338 } -  
339   -  
340 // Remove our temporary files 214 $listing = do_diff($all, $ignoreWhitespace, $highlighted, $newerFile, $olderFile, $newerFileHl, $olderFileHl);
341 unlink($oldtname); -  
342 unlink($newtname); -  
343 } 215 }
344 else 216 else
345 { 217 {
346 $vars["noprev"] = 1; 218 $listing = do_diff($all, $ignoreWhitespace, $highlighted, $newerFile, $olderFile, null, null);
347 } 219 }
348   220  
-   221 // Remove our temporary files
-   222 @unlink($newerFile);
349 $vars["version"] = $version; 223 @unlink($olderFile);
-   224 @unlink($newerFileHl);
-   225 @unlink($olderFileHl);
-   226 }
350   227  
351 if (!$rep->hasReadAccess($path, false)) 228 if (!$rep->hasReadAccess($path, false))
352 $vars["noaccess"] = true; -  
353   229 {
354 parseTemplate($rep->getTemplatePath()."header.tmpl", $vars, $listing); 230 $vars['error'] = $lang['NOACCESS'];
355 parseTemplate($rep->getTemplatePath()."diff.tmpl", $vars, $listing); -  
356 parseTemplate($rep->getTemplatePath()."footer.tmpl", $vars, $listing); 231 sendHeaderForbidden();
-   232 }
357 233  
358 ?> 234 renderTemplate('diff');