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 // blame.php 21 // blame.php
24 // 22 //
25 // Show the blame information of a file. 23 // Show the blame information 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';
32   30  
33 $vars['action'] = $lang['BLAME']; 31 $vars['action'] = $lang['BLAME'];
34   32  
-   33 // Make sure that we have a repository
-   34 if (!$rep)
-   35 {
-   36 renderTemplate404('blame','NOREP');
-   37 }
-   38  
35 $svnrep = new SVNRepository($rep); 39 $svnrep = new SVNRepository($rep);
36   40  
37 // If there's no revision info, go to the lastest revision for this path 41 // If there's no revision info, go to the lastest revision for this path
-   42 $history = $svnrep->getLog($path, 'HEAD', 1, false, 2, ($path == '/') ? '' : $peg);
-   43  
-   44 if (!$history)
-   45 {
-   46 unset($vars['error']);
38 $history = $svnrep->getLog($path, '', '', true); 47 $history = $svnrep->getLog($path, '', '', false, 2, ($path == '/') ? '' : $peg);
-   48  
-   49 if (!$history)
-   50 {
-   51 renderTemplate404('blame','NOPATH');
-   52 }
-   53 }
39 $youngest = $history->entries[0]->rev; 54 $youngest = ($history && isset($history->entries[0])) ? $history->entries[0]->rev : false;
40   55  
41 if (empty($rev)) 56 if (empty($rev))
-   57 {
42 $rev = $youngest; 58 $rev = $youngest;
-   59 }
-   60 else
-   61 {
-   62 $history = $svnrep->getLog($path, $rev, '', false, 2, $peg);
-   63 if (!$history)
-   64 {
-   65 renderTemplate404('blame','NOPATH');
-   66 }
-   67 }
43   68  
44 if ($path{0} != '/') 69 if ($path[0] != '/')
-   70 {
45 $ppath = '/'.$path; 71 $ppath = '/'.$path;
-   72 }
46 else 73 else
-   74 {
47 $ppath = $path; 75 $ppath = $path;
-   76 }
48   77  
49 // Find the parent path (or the whole path if it's already a directory) 78 // Find the parent path (or the whole path if it's already a directory)
50 $pos = strrpos($ppath, '/'); 79 $pos = strrpos($ppath, '/');
51 $parent = substr($ppath, 0, $pos + 1); 80 $parent = substr($ppath, 0, $pos + 1);
52   81  
53 $vars['repname'] = $rep->getDisplayName(); -  
54 $vars['rev'] = $rev; 82 $vars['rev'] = $rev;
55 $vars['path'] = $ppath; 83 $vars['peg'] = $peg;
-   84 $vars['path'] = str_replace('%2F', '/', rawurlencode($ppath));
-   85 $vars['safepath'] = escape($ppath);
56   86  
-   87 if (isset($history->entries[0]))
-   88 {
-   89 $vars['log'] = xml_entities($history->entries[0]->msg);
-   90 $vars['date'] = $history->entries[0]->date;
-   91 $vars['age'] = datetimeFormatDuration(time() - strtotime($history->entries[0]->date));
57 createDirLinks($rep, $ppath, $rev, $showchanged); 92 $vars['author'] = $history->entries[0]->author;
-   93 }
58   94  
-   95 createPathLinks($rep, $ppath, $passrev, $peg);
59 $listing = array(); 96 $passRevString = createRevAndPegString($rev, $peg);
60   97  
61 // Get the contents of the file 98 if ($rev != $youngest)
-   99 {
-   100 $vars['goyoungesturl'] = $config->getURL($rep, $path, 'blame').createRevAndPegString('', $peg);
-   101 $vars['goyoungestlink'] = '<a href="'.$vars['goyoungesturl'].'"'.($youngest ? ' title="'.$lang['REV'].' '.$youngest.'"' : '').'>'.$lang['GOYOUNGEST'].'</a>';
-   102 }
-   103  
62 $tfname = tempnam('temp', ''); 104 $revurl = $config->getURL($rep, $path, 'blame');
-   105  
-   106 if ($rev < $youngest)
-   107 {
63 $svnrep->getFileContents($path, $tfname, $rev, '', true); 108 $history2 = $svnrep->getLog($path, $rev, $youngest, true, 2, $peg);
-   109  
-   110 if (isset($history2->entries[1]))
-   111 {
-   112 $nextRev = $history2->entries[1]->rev;
-   113 if ($nextRev != $youngest)
-   114 {
-   115 $vars['nextrev'] = $nextRev;
-   116 $vars['nextrevurl'] = $revurl.createRevAndPegString($nextRev, $peg);
-   117 }
-   118 }
-   119  
-   120 unset($vars['error']);
-   121 }
-   122  
-   123 if (isset($history->entries[1]))
-   124 {
-   125 $prevRev = $history->entries[1]->rev;
-   126 $prevPath = $history->entries[1]->path;
-   127 $vars['prevrev'] = $prevRev;
-   128 $vars['prevrevurl'] = $revurl.createRevAndPegString($prevRev, $peg);
-   129 }
64   130  
-   131 $vars['revurl'] = $config->getURL($rep, $path, 'revision').$passRevString;
-   132 $vars['revlink'] = '<a href="'.$vars['revurl'].'">'.$lang['LASTMOD'].'</a>';
-   133  
-   134 $vars['logurl'] = $config->getURL($rep, $path, 'log').$passRevString;
-   135 $vars['loglink'] = '<a href="'.$vars['logurl'].'">'.$lang['VIEWLOG'].'</a>';
-   136  
-   137 $vars['filedetailurl'] = $config->getURL($rep, $path, 'file').$passRevString;
-   138 $vars['filedetaillink'] = '<a href="'.$vars['filedetailurl'].'">'.$lang['FILEDETAIL'].'</a>';
-   139  
-   140 if ($history == null || count($history->entries) > 1)
-   141 {
-   142 $vars['diffurl'] = $config->getURL($rep, $path, 'diff').$passRevString;
-   143 $vars['difflink'] = '<a href="'.$vars['diffurl'].'">'.$lang['DIFFPREV'].'</a>';
-   144 }
-   145  
65 $filecache = array(); 146 if ($rep->isRssEnabled())
-   147 {
-   148 $vars['rssurl'] = $config->getURL($rep, $path, 'rss').createRevAndPegString('', $peg);
-   149 $vars['rsslink'] = '<a href="'.$vars['rssurl'].'">'.$lang['RSSFEED'].'</a>';
-   150 }
-   151  
-   152 // Check for binary file type before grabbing blame information.
-   153 $svnMimeType = $svnrep->getProperty($path, 'svn:mime-type', $rev, $peg);
-   154  
-   155 if (!$rep->getIgnoreSvnMimeTypes() && preg_match('~application/*~', $svnMimeType))
-   156 {
-   157 $vars['warning'] = 'Cannot display blame info for binary file. (svn:mime-type = '.$svnMimeType.')';
-   158 $vars['javascript'] = '';
-   159 }
-   160 else
-   161 {
-   162 // Get the contents of the file
-   163 $tfname = tempnamWithCheck($config->getTempDir(), '');
-   164 $highlighted = $svnrep->getFileContents($path, $tfname, $rev, $peg, '', 'line');
66   165  
67 if ($file = fopen($tfname, 'r')) 166 if ($file = fopen($tfname, 'r'))
68 { 167 {
69 // Get the blame info 168 // Get the blame info
70 $tbname = tempnam('temp', ''); 169 $tbname = tempnamWithCheck($config->getTempDir(), '');
71 $svnrep->getBlameDetails($path, $tbname, $rev); -  
72 170  
73 $ent = true; -  
74 $extension = strrchr(basename($path), '.'); 171 $svnrep->getBlameDetails($path, $tbname, $rev, $peg);
75 if (($extension && isset($extEnscript[$extension]) && ('php' == $extEnscript[$extension])) || ($config->useEnscript)) -  
76 $ent = false; -  
77   172  
78 if ($blame = fopen($tbname, 'r')) 173 if ($blame = fopen($tbname, 'r'))
79 { 174 {
80 // Create an array of version/author/line 175 // Create an array of version/author/line
81 176  
82 $index = 0; 177 $index = 0;
-   178 $seen_rev = array();
-   179 $last_rev = '';
-   180 $row_class = '';
83 181  
84 while (!feof($blame) && !feof($file)) 182 while (!feof($blame) && !feof($file))
85 { 183 {
86 $blameline = fgets($blame); 184 $blameline = rtrim(fgets($blame), "\n\r");
87 185  
88 if ($blameline != '') 186 if ($blameline != '')
89 { 187 {
90 list($revision, $author) = sscanf($blameline, '%d %s'); 188 list($revision, $author, $remainder) = sscanf($blameline, '%d %s %s');
-   189 $empty = !$remainder;
91 190  
-   191 $listvar = &$listing[$index];
92 $listing[$index]['lineno'] = $index + 1; 192 $listvar['lineno'] = $index + 1;
93 193  
94 $url = $config->getURL($rep, $parent, 'dir'); 194 if ($last_rev != $revision)
-   195 {
95 $listing[$index]['revision'] = "<a href=\"${url}rev=$revision&amp;sc=1\">$revision</a>"; 196 $listvar['revision'] = '<a id="l'.$index.'-rev" class="blame-revision" href="'.$config->getURL($rep, $path, 'blame').createRevAndPegString($revision, $peg ? $peg : $rev).'">'.$revision.'</a>';
96   -  
-   197 $seen_rev[$revision] = 1;
-   198 $row_class = ($row_class == 'light') ? 'dark' : 'light';
97 $listing[$index]['author'] = $author; 199 $listvar['author'] = $author;
98 200 }
99 if ($ent) -  
100 $line = replaceEntities(rtrim(fgets($file)), $rep); -  
101 else 201 else
-   202 {
102 $line = rtrim(fgets($file)); 203 $listvar['revision'] = '';
103   -  
104 $listing[$index]['line'] = hardspace($line); 204 $listvar['author'] = '';
-   205 }
105 206  
106 if (trim($listing[$index]['line']) == '') 207 $listvar['row_class'] = $row_class;
107 $listing[$index]['line'] = '&nbsp;'; 208 $last_rev = $revision;
108 209  
-   210 $line = rtrim(fgets($file), "\n\r");
-   211 if (!$highlighted)
-   212 {
-   213 $line = escape(toOutputEncoding($line));
-   214 }
-   215 $listvar['line'] = ($empty) ? '&nbsp;' : wrapInCodeTagIfNecessary($line);
109 $index++; 216 $index++;
110 } 217 }
111 } 218 }
112 -  
113 fclose($blame); 219 fclose($blame);
114 } 220 }
115 221  
116 fclose($file); 222 fclose($file);
-   223 @unlink($tbname);
117 } 224 }
-   225 @unlink($tfname);
118   226  
-   227 // Build the necessary JavaScript as an array of lines, then join them with \n
119 unlink($tfname); 228 $javascript = array();
-   229 $javascript[] = '<script type="text/javascript" src="'.$locwebsvnhttp.'/javascript/blame-popup.js"></script>';
-   230 $javascript[] = '<script type="text/javascript">';
120 unlink($tbname); 231 $javascript[] = '/* <![CDATA[ */';
-   232 $javascript[] = 'var rev = new Array();';
121   233  
-   234 ksort($seen_rev); // Sort revisions in descending order by key
-   235 if (empty($peg))
-   236 {
-   237 $peg = $rev;
-   238 }
-   239 if (!isset($vars['warning']))
-   240 {
122 $vars['version'] = $version; 241 foreach ($seen_rev as $key => $val)
-   242 {
-   243 $history = $svnrep->getLog($path, $key, $key, false, 1, $peg);
123   244  
124 if (!$rep->hasReadAccess($path, false)) 245 if ($history && $history->curEntry)
-   246 {
125 $vars['noaccess'] = true; 247 $javascript[] = 'rev['.$key.'] = \'<div class="date">'.$history->curEntry->date.'</div><div class="msg">'.addslashes(preg_replace('/\n/', ' ', $history->curEntry->msg)).'</div>\';';
-   248 }
-   249 }
-   250 }
126   251  
-   252 $javascript[] = '/* ]]> */';
-   253 $javascript[] = '</script>';
127 parseTemplate($rep->getTemplatePath().'header.tmpl', $vars, $listing); 254 $vars['javascript'] = implode("\n", $javascript);
-   255 }
-   256  
128 parseTemplate($rep->getTemplatePath().'blame.tmpl', $vars, $listing); 257 if (!$rep->hasReadAccess($path, false))
-   258 {
129 parseTemplate($rep->getTemplatePath().'footer.tmpl', $vars, $listing); 259 $vars['error'] = $lang['NOACCESS'];
-   260 sendHeaderForbidden();
-   261 }
130 262  
131 ?> -  
-   263 renderTemplate('blame');