Indefero

Indefero Commit Details


Date:2008-07-26 18:31:10 (16 years 5 months ago)
Author:Loic d'Anterroches
Branch:dev, develop, feature-issue_links, feature.better-home, feature.content-md5, feature.diff-whitespace, feature.download-md5, feature.issue-links, feature.issue-of-others, feature.issue-summary, feature.search-filter, feature.webrepos, feature.wiki-default-page, master, newdiff, release-1.1, release-1.2, release-1.3, svn
Commit:c915f8fccfc20a1a491bb88dd7848005dc1641ff
Parents: f57a0ec08bfbaa830f4f7fb39f1f7e39d400ecb3
Message:Added the changelog and fixed the source browser.

The source browser is normally a little bit more robust.
Changes:

File differences

src/IDF/Git.php
4141
4242
4343
44
44
4545
4646
4747
48
48
4949
5050
5151
52
53
52
53
54
5455
55
56
5657
5758
5859
......
6061
6162
6263
63
64
6465
6566
6667
6768
6869
6970
71
72
73
74
75
7076
7177
7278
7379
74
75
76
77
80
81
82
83
84
85
86
87
88
7889
7990
8091
81
92
8293
8394
8495
......
8899
89100
90101
91
92
93
102
103
104
94105
95
106
96107
97108
98
109
99110
100111
101112
......
134145
135146
136147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
137248
     *
     * 'perm', 'type', 'size', 'hash', 'file'
     *
     * @param string Commit/Branch ('HEAD')
     * @param string Tree ('HEAD')
     * @param string Base folder ('')
     * @return array
     */
    public function filesInTree($commit='HEAD', $basefolder='')
    public function filesInTree($tree='HEAD', $basefolder='')
    {
        if (is_object($basefolder)) {
            $base = $basefolder;
        } else if ($basefolder != ''
            and
        } else if (
                   $basefolder !=  ''
                   and
            (
             (false === ($base=$this->getFileInfo($basefolder, $commit)))
             (false === ($base=$this->getFileInfo($basefolder, $tree)))
             or
             ($base->type != 'tree')
             )) {
        } else {
            // no base
            $base = (object) array('file' => '',
                                   'hash' => $commit);
                                   'hash' => $tree);
        }
       
        $res = array();
        $out = array();
        $cmd = sprintf('GIT_DIR=%s git-ls-tree -t -l %s', $this->repo, $base->hash);
        exec($cmd, &$out);
        $rawlog = array();
        $cmd = sprintf('GIT_DIR=%s git log --raw --abbrev=40 --pretty=oneline',
                       $this->repo);
        exec($cmd, &$rawlog);
        $rawlog = implode("\n", array_reverse($rawlog));
        $current_dir = getcwd();
        chdir(substr($this->repo, 0, -5));
        foreach ($out as $line) {
            list($perm, $type, $hash, $size, $file) = preg_split('/ |\t/', $line, 5, PREG_SPLIT_NO_EMPTY);
            $cm = array();
            $cmd = sprintf('GIT_DIR=%s git log -1 --pretty=format:\'%%H %%at %%s\' %s -- %s', $this->repo, $commit, ($base->file) ? $base->file.'/'.$file : $file);
            exec($cmd, &$cm);
            list($h, $time, $log) = explode(' ', $cm[0], 3);
            $matches = array();
            $date = '1970-01-01 12:00:00';
            $log = '';
            if ($type == 'blob' and preg_match('/^\:\d{6} \d{6} [0-9a-f]{40} '.$hash.' .*^([0-9a-f]{40})/msU',
                           $rawlog, &$matches)) {
                $_c = $this->getCommit($matches[1]);
                $date = $_c->date;
                $log = $_c->title;
            }
            $res[] = (object) array('perm' => $perm, 'type' => $type,
                                    'size' => $size, 'hash' => $hash,
                                    'fullpath' => ($base->file) ? $base->file.'/'.$file : $file,
                                    'log' => $log, 'time' => $time,
                                    'log' => $log, 'date' => $date,
                                    'file' => $file);
        }
        chdir($current_dir);
    /**
     * Get the file info.
     *
     * @param string Tree to test
     * @param string Commit/Branch ('HEAD')
     * @return false or Tree information
     * @param string File
     * @param string Tree ('HEAD')
     * @return false Information
     */
    public function getFileInfo($totest, $commit='HEAD')
    public function getFileInfo($totest, $tree='HEAD')
    {
        $cmd_tmpl = 'GIT_DIR=%s git-ls-tree -r -t -l %s';
        $cmd = sprintf($cmd_tmpl, $this->repo, $commit);
        $cmd = sprintf($cmd_tmpl, $this->repo, $tree);
        $out = array();
        exec($cmd, &$out);
        foreach ($out as $line) {
        }
        return $res;
    }
    /**
     * Get commit details.
     *
     * @param string Commit ('HEAD').
     * @return array Changes.
     */
    public function getCommit($commit='HEAD')
    {
        $cmd = sprintf('GIT_DIR=%s git show --date=iso --pretty=medium %s',
                       escapeshellarg($this->repo), $commit);
        $out = array();
        exec($cmd, &$out);
        $log = array();
        $change = array();
        $inchange = false;
        foreach ($out as $line) {
            if (!$inchange and 0 === strpos($line, 'diff --git a')) {
                $inchange = true;
            }
            if ($inchange) {
                $change[] = $line;
            } else {
                $log[] = $line;
            }
        }
        $out = self::parseLog($log);
        $out[0]->changes = $change;
        return $out[0];
    }
    /**
     * Get latest changes.
     *
     * @param string Tree ('HEAD').
     * @param int Number of changes (10).
     * @return array Changes.
     */
    public function getChangeLog($tree='HEAD', $n=10)
    {
        $format = 'commit %H%nAuthor: %an <%ae>%nTree: %T%nDate: %ai%n%n%s%n%n%b';
        if ($n === null) $n = '';
        else $n = ' -'.$n;
        $cmd = sprintf('GIT_DIR=%s git log%s --date=iso --pretty=format:\'%s\' %s',
                       escapeshellarg($this->repo), $n, $format, $tree);
        $out = array();
        exec($cmd, &$out);
        return self::parseLog($out, 4);
    }
    /**
     * Parse the log lines of a --pretty=medium log output.
     *
     * @param array Lines.
     * @param int Number of lines in the headers (3)
     * @return array Change log.
     */
    public static function parseLog($lines, $hdrs=3)
    {
        $res = array();
        $c = array();
        $i = 0;
        $hdrs += 2;
        foreach ($lines as $line) {
            $i++;
            if (0 === strpos($line, 'commit')) {
                if (count($c) > 0) {
                    $c['full_message'] = trim($c['full_message']);
                    $res[] = (object) $c;
                }
                $c = array();
                $c['commit'] = trim(substr($line, 7));
                $c['full_message'] = '';
                $i=1;
                continue;
            }
            if ($i == $hdrs) {
                $c['title'] = trim($line);
                continue;
            }
            $match = array();
            if (preg_match('/(\S+)\s*:\s*(.*)/', $line, $match)) {
                $match[1] = strtolower($match[1]);
                $c[$match[1]] = trim($match[2]);
                if ($match[1] == 'date') {
                    $c['date'] = gmdate('Y-m-d H:i:s', strtotime($match[2]));
                }
                continue;
            }
            if ($i > ($hdrs+1)) {
                $c['full_message'] .= trim($line)."\n";
                continue;
            }
        }
        $c['full_message'] = trim($c['full_message']);
        $res[] = (object) $c;
        return $res;
    }
}
src/IDF/Views/Source.php
3131
3232
3333
34
34
3535
36
37
38
39
40
41
42
43
44
45
46
47
48
49
3650
3751
3852
......
4155
4256
4357
44
58
59
60
61
62
63
64
65
4566
4667
4768
4869
4970
50
71
72
73
5174
5275
5376
......
5780
5881
5982
60
61
83
6284
63
85
6486
65
66
6787
6888
6989
7090
71
91
92
93
94
95
96
7297
7398
7499
75100
101
102
103
104
105
76106
77107
78108
79109
80110
81111
82
112
113
83114
84115
116
85117
86118
87119
88120
89121
90
122
91123
92124
93125
......
97129
98130
99131
100
132
101133
102134
103135
 */
class IDF_Views_Source
{
    public function index($request, $match)
    public function changeLog($request, $match)
    {
        $title = sprintf('%s Git Change Log', (string) $request->project);
        $git = new IDF_Git(Pluf::f('git_repository'));
        $branches = $git->getBranches();
        $commit = $match[2];
        $res = $git->getChangeLog($commit, 50);
        return Pluf_Shortcuts_RenderToResponse('source/changelog.html',
                                               array(
                                                     'page_title' => $title,
                                                     'title' => $title,
                                                     'changes' => $res,
                                                     'commit' => $commit,
                                                     'branches' => $branches,
                                                     ),
                                               $request);
    }
    public function treeBase($request, $match)
        $git = new IDF_Git(Pluf::f('git_repository'));
        $branches = $git->getBranches();
        $res = $git->filesInTree($match[2]);
        $commit = $match[2];
        $tree = $match[2];
        $cobject = '';
        $tree_in = in_array($tree, $branches);
        foreach ($git->getChangeLog('', null) as $change) {
            if ($change->tree == $tree) {
                $cobject = $change;
            }
        }
        return Pluf_Shortcuts_RenderToResponse('source/tree.html',
                                               array(
                                                     'page_title' => $title,
                                                     'title' => $title,
                                                     'files' => $res,
                                                     'commit' => $commit,
                                                     'cobject' => $cobject,
                                                     'tree' => $tree,
                                                     'tree_in' => $tree_in,
                                                     'branches' => $branches,
                                                     ),
                                               $request);
    {
        $title = sprintf('%s Git Source Tree', (string) $request->project);
        $git = new IDF_Git(Pluf::f('git_repository'));
        $branches = $git->getBranches();
        $commit = $match[2];
        $tree = $match[2];
        $request_file = $match[3];
        $request_file_info = $git->getFileInfo($request_file);
        $request_file_info = $git->getFileInfo($request_file, $tree);
        if (!$request_file_info) throw new Pluf_HTTP_Error404();
        $bc = self::makeBreadCrumb($request->project, $commit, $request_file_info->file);
        $page_title = $bc.' - '.$title;
        if ($request_file_info->type != 'tree') {
            return new Pluf_HTTP_Response($git->getBlob($request_file_info->hash),
                                          'application/octet-stream');
        }
        $res = $git->filesInTree($commit, $request_file_info);
        $bc = self::makeBreadCrumb($request->project, $tree, $request_file_info->file);
        $page_title = $bc.' - '.$title;
        $branches = $git->getBranches();
        $cobject = '';
        $tree_in = in_array($tree, $branches);
        $res = $git->filesInTree($tree, $request_file_info);
        // try to find the previous level if it exists.
        $prev = split('/', $request_file);
        $l = array_pop($prev);
        $previous = substr($request_file, 0, -strlen($l.' '));
        foreach ($git->getChangeLog('', null) as $change) {
            if ($change->tree == $tree) {
                $cobject = $change; //$git->getCommit($tree);
            }
        }
        return Pluf_Shortcuts_RenderToResponse('source/tree.html',
                                               array(
                                                     'page_title' => $page_title,
                                                     'title' => $title,
                                                     'breadcrumb' => $bc,
                                                     'files' => $res,
                                                     'commit' => $commit,
                                                     'tree' => $tree,
                                                     'cobject' => $cobject,
                                                     'base' => $request_file_info->file,
                                                     'prev' => $previous,
                                                     'tree_in' => $tree_in,
                                                     'branches' => $branches,
                                                     ),
                                               $request);
    }
    public static function makeBreadCrumb($project, $commit, $file, $sep='/')
    public static function makeBreadCrumb($project, $tree, $file, $sep='/')
    {
        $elts = split('/', $file);
        $out = array();
            $stack .= ($i==0) ? $elt : '/'.$elt;
            $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::tree',
                                            array($project->shortname,
                                                  $commit, $stack));
                                                  $tree, $stack));
            $out[] = '<a href="'.$url.'">'.Pluf_esc($elt).'</a>';
            $i++;
        }
src/IDF/conf/views.php
110110
111111
112112
113
114
115
116
117
118
113119
114120
115121
               'model' => 'IDF_Views_Source',
               'method' => 'tree');
$ctl[] = array('regex' => '#^/p/(\w+)/source/changes/(\w+)/$#',
               'base' => $base,
               'priority' => 4,
               'model' => 'IDF_Views_Source',
               'method' => 'changeLog');
// ---------- ADMIN --------------------------------------
src/IDF/templates/base.html
4343
4444
4545
46
46
4747
4848
4949
{if $project}
{*  <a href="{url 'IDF_Views_Project::home', array($project.shortname)}"{block tabhome}{/block}>{trans 'Project Home'}</a> *}
  <a href="{url 'IDF_Views_Issue::index', array($project.shortname)}"{block tabissues}{/block}>{trans 'Issues'}</a>
  <a href="{url 'IDF_Views_Source::index', array($project.shortname)}"{block tabsource}{/block}>{trans 'Source'}</a>
  <a href="{url 'IDF_Views_Source::treeBase', array($project.shortname, 'master')}"{block tabsource}{/block}>{trans 'Source'}</a>
{if $isOwner}
  <a href="{url 'IDF_Views_Project::admin', array($project.shortname)}"{block tabadmin}{/block}>{trans 'Administer'}</a>{/if}{/if}
</div>
src/IDF/templates/source/base.html
22
33
44
5
5
6
67
78
89
{block tabsource} class="active"{/block}
{block subtabs}
<div id="sub-tabs">
{trans 'Source Tree'}
{trans 'Source Tree'} |
<a href="{url 'IDF_Views_Source::changeLog', array($project.shortname, 'master')}">{trans 'Change Log'}</a>
</div>
{/block}
{block title}{$title}{/block}
src/IDF/templates/source/changelog.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{extends "source/base.html"}
{block docclass}yui-t1{/block}
{block body}
<table summary="" class="tree-list">
<thead>
<tr>
<th>{trans 'Age'}</th>
<th>{trans 'Message'}</th>
<th>{trans 'Details'}</th>
</tr>
</thead>
<tbody>
{foreach $changes as $change}
{aurl 'url', 'IDF_Views_Source::treeBase', array($project.shortname, $change.tree)}
<tr>
<td><a href="{$url}">{$change.date|dateago:"wihtout"}</a></td>
<td>{$change.title}{if $change.full_message}<br /><span class="smaller">{$change.full_message}</span>{/if}</td>
<td><span class="smaller">{trans 'Tree:'}&nbsp;<a href="{$url}">{$change.tree}</a><br />
{trans 'By:'} {$change.author|strip_tags} {* this remove the email address *}
</span></td>
</tr>
{/foreach}
</tbody>
</table>
{/block}
{block context}
<p><strong>{trans 'Branches:'}</strong><br />
{foreach $branches as $branch}
{aurl 'url', 'IDF_Views_Source::changeLog', array($project.shortname, $branch)}
<span class="label{if $commit == $branch} active{/if}"><a href="{$url}" class="label">{$branch}</a></span><br />
{/foreach}
</p>
{/block}
src/IDF/templates/source/tree.html
11
22
33
4
4
55
66
77
......
1010
1111
1212
13
14
13
14
15
16
17
18
1519
1620
1721
1822
19
23
2024
2125
2226
23
27
2428
2529
26
27
28
30
2931
32
33
3034
3135
3236
......
3842
3943
4044
41
45
4246
4347
4448
{extends "source/base.html"}
{block docclass}yui-t1{/block}
{block body}
<h2><a href="{url 'IDF_Views_Source::treeBase', array($project.shortname, $commit)}">{trans 'Root'}</a><span class="sep">/</span>{if $breadcrumb}{$breadcrumb|safe}{/if}</h2>
<h2><a href="{url 'IDF_Views_Source::treeBase', array($project.shortname, $tree)}">{trans 'Root'}</a><span class="sep">/</span>{if $breadcrumb}{$breadcrumb|safe}{/if}</h2>
<table summary="" class="tree-list">
<thead>
<tr>
<th>{trans 'Message'}</th>
<th>{trans 'Size'}</th>
</tr>
</thead>
<tbody>
</thead>{if !$tree_in}
{aurl 'url', 'IDF_Views_Source::treeBase', array($project.shortname, $tree)}
<tfoot>
<tr><th colspan="5">{blocktrans}In tree <a href="{$url}">{$tree}</a> created {$cobject.date|dateago}.{/blocktrans}</th></tr>
</tfoot>
{/if}<tbody>
{if $base}
<tr>
<td>&nbsp;</td>
<td colspan="4">
<a href="{url 'IDF_Views_Source::tree', array($project.shortname, $commit, $prev)}">..</a></td>
<a href="{url 'IDF_Views_Source::tree', array($project.shortname, $tree, $prev)}">..</a></td>
</tr>
{/if}
{foreach $files as $file}
{aurl 'url', 'IDF_Views_Source::tree', array($project.shortname, $commit, $file.fullpath)}
{aurl 'url', 'IDF_Views_Source::tree', array($project.shortname, $tree, $file.fullpath)}
<tr>
<td><img src="{media '/idf/img/'~$file.type~'.png'}" alt="{$file.type}" /></td>
<td><a href="{$url}">{$file.file}</a></td>
<td><span class="smaller">{$file.time|timeago:"wihtout"}</span></td>
<td{if $file.type != 'blob'} colspan="2"{/if}><span class="smaller">{$file.log}</span></td>
<td{if $file.type != 'blob'} colspan="4"{/if}><a href="{$url}">{$file.file}</a></td>
{if $file.type == 'blob'}
<td><span class="smaller">{$file.date|dateago:"wihtout"}</span></td>
<td><span class="smaller">{$file.log}</span></td>
<td>{$file.size|size}</td>{/if}
</tr>
{/foreach}
<p><strong>{trans 'Branches:'}</strong><br />
{foreach $branches as $branch}
{aurl 'url', 'IDF_Views_Source::treeBase', array($project.shortname, $branch)}
<span class="label{if $commit == $branch} active{/if}"><a href="{$url}" class="label">{$branch}</a></span><br />
<span class="label{if $tree == $branch} active{/if}"><a href="{$url}" class="label">{$branch}</a></span><br />
{/foreach}
</p>
{/block}
www/media/idf/css/style.css
273273
274274
275275
276
277
278
279
280
281
282
283
284
285
276286
277287
278288
  vertical-align: top;
}
table.tree-list tfoot th {
  text-align: right;
  font-weight: normal;
}
table.recent-issues tfoot th a {
  color: #000;
  font-weight: normal;
}
/**

Archive Download the corresponding diff file

Page rendered in 0.15011s using 13 queries.