InDefero

Sign in or create your account | Project List | Help

InDefero Git Source Tree

Root/src/IDF/Views/Source.php

Source at commit 7383e18dff19e7e6a1e56d55cdfbfa109e91bfb3 created 1 year 7 months ago.
By Loic d'Anterroches, Fixed issue 4, with fine control over the tabs access.
1<?php
2/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3/*
4# ***** BEGIN LICENSE BLOCK *****
5# This file is part of InDefero, an open source project management application.
6# Copyright (C) 2008 Céondo Ltd and contributors.
7#
8# InDefero is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# InDefero is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21#
22# ***** END LICENSE BLOCK ***** */
23
24Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
25Pluf::loadFunction('Pluf_Shortcuts_RenderToResponse');
26Pluf::loadFunction('Pluf_Shortcuts_GetObjectOr404');
27Pluf::loadFunction('Pluf_Shortcuts_GetFormForModel');
28
29/**
30 * View git repository.
31 */
32class IDF_Views_Source
33{
34    public $changeLog_precond = array('IDF_Precondition::accessSource');
35    public function changeLog($request, $match)
36    {
37        $title = sprintf(__('%s Git Change Log'), (string) $request->project);
38        $git = new IDF_Git($request->project->getGitRepository());
39        $branches = $git->getBranches();
40        $commit = $match[2];
41        $res = $git->getChangeLog($commit, 25);
42        return Pluf_Shortcuts_RenderToResponse('source/changelog.html',
43                                               array(
44                                                     'page_title' => $title,
45                                                     'title' => $title,
46                                                     'changes' => $res,
47                                                     'commit' => $commit,
48                                                     'branches' => $branches,
49                                                     ),
50                                               $request);
51    }
52
53    public $treeBase_precond = array('IDF_Precondition::accessSource');
54    public function treeBase($request, $match)
55    {
56        $title = sprintf(__('%s Git Source Tree'), (string) $request->project);
57        $git = new IDF_Git($request->project->getGitRepository());
58        $commit = $match[2];
59        $branches = $git->getBranches();
60        if ('commit' != $git->testHash($commit)) {
61            // Redirect to the first branch
62            $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
63                                            array($request->project->shortname,
64                                                  $branches[0]));
65            return new Pluf_HTTP_Response_Redirect($url);
66        }
67        $res = $git->filesAtCommit($commit);
68        $cobject = $git->getCommit($commit);
69        $tree_in = in_array($commit, $branches);
70        return Pluf_Shortcuts_RenderToResponse('source/tree.html',
71                                               array(
72                                                     'page_title' => $title,
73                                                     'title' => $title,
74                                                     'files' => $res,
75                                                     'cobject' => $cobject,
76                                                     'commit' => $commit,
77                                                     'tree_in' => $tree_in,
78                                                     'branches' => $branches,
79                                                     ),
80                                               $request);
81    }
82
83    public $tree_precond = array('IDF_Precondition::accessSource');
84    public function tree($request, $match)
85    {
86        $title = sprintf(__('%s Git Source Tree'), (string) $request->project);
87        $git = new IDF_Git($request->project->getGitRepository());
88        $branches = $git->getBranches();
89        $commit = $match[2];
90        if ('commit' != $git->testHash($commit)) {
91            // Redirect to the first branch
92            $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
93                                            array($request->project->shortname,
94                                                  $branches[0]));
95            return new Pluf_HTTP_Response_Redirect($url);
96        }
97        $request_file = $match[3];
98        $request_file_info = $git->getFileInfo($request_file, $commit);
99        if (!$request_file_info) {
100            // Redirect to the first branch
101            $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
102                                            array($request->project->shortname,
103                                                  $branches[0]));
104            return new Pluf_HTTP_Response_Redirect($url);
105        }
106        if ($request_file_info->type != 'tree') {
107            $info = self::getMimeType($request_file_info->file);
108            $rep = new Pluf_HTTP_Response($git->getBlob($request_file_info->hash),
109                                          $info[0]);
110            $rep->headers['Content-Disposition'] = 'attachment; filename="'.$info[1].'"';
111            return $rep;
112        }
113        $bc = self::makeBreadCrumb($request->project, $commit, $request_file_info->file);
114        $page_title = $bc.' - '.$title;
115        $cobject = $git->getCommit($commit);
116        $tree_in = in_array($commit, $branches);
117        $res = $git->filesAtCommit($commit, $request_file);
118        // try to find the previous level if it exists.
119        $prev = split('/', $request_file);
120        $l = array_pop($prev);
121        $previous = substr($request_file, 0, -strlen($l.' '));
122        return Pluf_Shortcuts_RenderToResponse('source/tree.html',
123                                               array(
124                                                     'page_title' => $page_title,
125                                                     'title' => $title,
126                                                     'breadcrumb' => $bc,
127                                                     'files' => $res,
128                                                     'commit' => $commit,
129                                                     'cobject' => $cobject,
130                                                     'base' => $request_file_info->file,
131                                                     'prev' => $previous,
132                                                     'tree_in' => $tree_in,
133                                                     'branches' => $branches,
134                                                     ),
135                                               $request);
136    }
137
138    public static function makeBreadCrumb($project, $commit, $file, $sep='/')
139    {
140        $elts = split('/', $file);
141        $out = array();
142        $stack = '';
143        $i = 0;
144        foreach ($elts as $elt) {
145            $stack .= ($i==0) ? $elt : '/'.$elt;
146            $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::tree',
147                                            array($project->shortname,
148                                                  $commit, $stack));
149            $out[] = '<a href="'.$url.'">'.Pluf_esc($elt).'</a>';
150            $i++;
151        }
152        return '<span class="breadcrumb">'.implode('<span class="sep">'.$sep.'</span>', $out).'</span>';
153    }
154
155    public $commit_precond = array('IDF_Precondition::accessSource');
156    public function commit($request, $match)
157    {
158        $git = new IDF_Git($request->project->getGitRepository());
159        $commit = $match[2];
160        $branches = $git->getBranches();
161        if ('commit' != $git->testHash($commit)) {
162            // Redirect to the first branch
163            $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
164                                            array($request->project->shortname,
165                                                  $branches[0]));
166            return new Pluf_HTTP_Response_Redirect($url);
167        }
168        $title = sprintf(__('%s Commit Details'), (string) $request->project);
169        $page_title = sprintf(__('%s Commit Details - %s'), (string) $request->project, $commit);
170        $cobject = $git->getCommit($commit);
171        $diff = new IDF_Diff($cobject->changes);
172        $diff->parse();
173        return Pluf_Shortcuts_RenderToResponse('source/commit.html',
174                                               array(
175                                                     'page_title' => $page_title,
176                                                     'title' => $title,
177                                                     'diff' => $diff,
178                                                     'cobject' => $cobject,
179                                                     'commit' => $commit,
180                                                     'branches' => $branches,
181                                                     ),
182                                               $request);
183    }
184
185    /**
186     * Get a zip archive of the current commit.
187     *
188     */
189    public $download_precond = array('IDF_Precondition::accessSource');
190    public function download($request, $match)
191    {
192        $commit = trim($match[2]);
193        $git = new IDF_Git($request->project->getGitRepository());
194        $branches = $git->getBranches();
195        if ('commit' != $git->testHash($commit)) {
196            // Redirect to the first branch
197            $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
198                                            array($request->project->shortname,
199                                                  $branches[0]));
200            return new Pluf_HTTP_Response_Redirect($url);
201        }
202        $base = $request->project->shortname.'-'.$commit;
203        $cmd = $git->getArchiveCommand($commit, $base.'/');
204        $rep = new Pluf_HTTP_Response_CommandPassThru($cmd, 'application/x-zip');
205        $rep->headers['Content-Transfer-Encoding'] = 'binary';
206        $rep->headers['Content-Disposition'] = 'attachment; filename="'.$base.'.zip"';
207        return $rep;
208    }
209
210    /**
211     * Find the mime type of a file.
212     *
213     * Use /etc/mime.types to find the type.
214     *
215     * @param string Filename/Filepath
216     * @param string Path to the mime types database ('/etc/mime.types')
217     * @param array Mime type found or 'application/octet-stream' and basename
218     */
219    public static function getMimeType($file, $src='/etc/mime.types')
220    {
221        $mimes = preg_split("/\015\012|\015|\012/", file_get_contents($src));
222        $info = pathinfo($file);
223        if (isset($info['extension'])) {
224            foreach ($mimes as $mime) {
225                if ('#' != substr($mime, 0, 1)) {
226                    $elts = preg_split('/ |\t/', $mime, -1, PREG_SPLIT_NO_EMPTY);
227                    if (in_array($info['extension'], $elts)) {
228                        return array($elts[0], $info['basename']);
229                    }
230                }
231            }
232        } else {
233            // we consider that if no extension and base name is all
234            // uppercase, then we have a text file.
235            if ($info['basename'] == strtoupper($info['basename'])) {
236                return array('text/plain', $info['basename']);
237            }
238        }
239        return array('application/octet-stream', $info['basename']);
240    }
241}
242
243function IDF_Views_Source_PrettySize($size)
244{
245    return Pluf_Template::markSafe(Pluf_Utils::prettySize($size));
246}
247
248

Archive Download this file

Branches:
dev
master
newdiff
svn