Indefero

Indefero Git Source Tree

Root/src/IDF/Views/Source.php

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 function changeLog($request, $match)
35 {
36 $title = sprintf(__('%s Git Change Log'), (string) $request->project);
37 $git = new IDF_Git($request->project->getGitRepository());
38 $branches = $git->getBranches();
39 $commit = $match[2];
40 $res = $git->getChangeLog($commit, 25);
41 return Pluf_Shortcuts_RenderToResponse('source/changelog.html',
42 array(
43 'page_title' => $title,
44 'title' => $title,
45 'changes' => $res,
46 'commit' => $commit,
47 'branches' => $branches,
48 ),
49 $request);
50 }
51
52 public function treeBase($request, $match)
53 {
54 $title = sprintf(__('%s Git Source Tree'), (string) $request->project);
55 $git = new IDF_Git($request->project->getGitRepository());
56 $commit = $match[2];
57 $branches = $git->getBranches();
58 if ('commit' != $git->testHash($commit)) {
59 // Redirect to the first branch
60 $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
61 array($request->project->shortname,
62 $branches[0]));
63 return new Pluf_HTTP_Response_Redirect($url);
64 }
65 $res = $git->filesAtCommit($commit);
66 $cobject = $git->getCommit($commit);
67 $tree_in = in_array($commit, $branches);
68 return Pluf_Shortcuts_RenderToResponse('source/tree.html',
69 array(
70 'page_title' => $title,
71 'title' => $title,
72 'files' => $res,
73 'cobject' => $cobject,
74 'commit' => $commit,
75 'tree_in' => $tree_in,
76 'branches' => $branches,
77 ),
78 $request);
79 }
80
81 public function tree($request, $match)
82 {
83 $title = sprintf(__('%s Git Source Tree'), (string) $request->project);
84 $git = new IDF_Git($request->project->getGitRepository());
85 $branches = $git->getBranches();
86 $commit = $match[2];
87 if ('commit' != $git->testHash($commit)) {
88 // Redirect to the first branch
89 $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
90 array($request->project->shortname,
91 $branches[0]));
92 return new Pluf_HTTP_Response_Redirect($url);
93 }
94 $request_file = $match[3];
95 $request_file_info = $git->getFileInfo($request_file, $commit);
96 if (!$request_file_info) {
97 // Redirect to the first branch
98 $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
99 array($request->project->shortname,
100 $branches[0]));
101 return new Pluf_HTTP_Response_Redirect($url);
102 }
103 if ($request_file_info->type != 'tree') {
104 $info = self::getMimeType($request_file_info->file);
105 $rep = new Pluf_HTTP_Response($git->getBlob($request_file_info->hash),
106 $info[0]);
107 $rep->headers['Content-Disposition'] = 'attachment; filename="'.$info[1].'"';
108 return $rep;
109 }
110 $bc = self::makeBreadCrumb($request->project, $commit, $request_file_info->file);
111 $page_title = $bc.' - '.$title;
112 $cobject = $git->getCommit($commit);
113 $tree_in = in_array($commit, $branches);
114 $res = $git->filesAtCommit($commit, $request_file);
115 // try to find the previous level if it exists.
116 $prev = split('/', $request_file);
117 $l = array_pop($prev);
118 $previous = substr($request_file, 0, -strlen($l.' '));
119 return Pluf_Shortcuts_RenderToResponse('source/tree.html',
120 array(
121 'page_title' => $page_title,
122 'title' => $title,
123 'breadcrumb' => $bc,
124 'files' => $res,
125 'commit' => $commit,
126 'cobject' => $cobject,
127 'base' => $request_file_info->file,
128 'prev' => $previous,
129 'tree_in' => $tree_in,
130 'branches' => $branches,
131 ),
132 $request);
133 }
134
135 public static function makeBreadCrumb($project, $commit, $file, $sep='/')
136 {
137 $elts = split('/', $file);
138 $out = array();
139 $stack = '';
140 $i = 0;
141 foreach ($elts as $elt) {
142 $stack .= ($i==0) ? $elt : '/'.$elt;
143 $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::tree',
144 array($project->shortname,
145 $commit, $stack));
146 $out[] = '<a href="'.$url.'">'.Pluf_esc($elt).'</a>';
147 $i++;
148 }
149 return '<span class="breadcrumb">'.implode('<span class="sep">'.$sep.'</span>', $out).'</span>';
150 }
151
152 public function commit($request, $match)
153 {
154 $git = new IDF_Git($request->project->getGitRepository());
155 $commit = $match[2];
156 $branches = $git->getBranches();
157 if ('commit' != $git->testHash($commit)) {
158 // Redirect to the first branch
159 $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
160 array($request->project->shortname,
161 $branches[0]));
162 return new Pluf_HTTP_Response_Redirect($url);
163 }
164 $title = sprintf(__('%s Commit Details'), (string) $request->project);
165 $page_title = sprintf(__('%s Commit Details - %s'), (string) $request->project, $commit);
166 $cobject = $git->getCommit($commit);
167 $diff = new IDF_Diff($cobject->changes);
168 $diff->parse();
169 return Pluf_Shortcuts_RenderToResponse('source/commit.html',
170 array(
171 'page_title' => $page_title,
172 'title' => $title,
173 'diff' => $diff,
174 'cobject' => $cobject,
175 'commit' => $commit,
176 'branches' => $branches,
177 ),
178 $request);
179 }
180
181 /**
182 * Get a zip archive of the current commit.
183 *
184 */
185 public function download($request, $match)
186 {
187 $commit = trim($match[2]);
188 $git = new IDF_Git($request->project->getGitRepository());
189 $branches = $git->getBranches();
190 if ('commit' != $git->testHash($commit)) {
191 // Redirect to the first branch
192 $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
193 array($request->project->shortname,
194 $branches[0]));
195 return new Pluf_HTTP_Response_Redirect($url);
196 }
197 $base = $request->project->shortname.'-'.$commit;
198 $cmd = $git->getArchiveCommand($commit, $base.'/');
199 $rep = new Pluf_HTTP_Response_CommandPassThru($cmd, 'application/x-zip');
200 $rep->headers['Content-Transfer-Encoding'] = 'binary';
201 $rep->headers['Content-Disposition'] = 'attachment; filename="'.$base.'.zip"';
202 return $rep;
203 }
204
205 /**
206 * Find the mime type of a file.
207 *
208 * Use /etc/mime.types to find the type.
209 *
210 * @param string Filename/Filepath
211 * @param string Path to the mime types database ('/etc/mime.types')
212 * @param array Mime type found or 'application/octet-stream' and basename
213 */
214 public static function getMimeType($file, $src='/etc/mime.types')
215 {
216 $mimes = preg_split("/\015\012|\015|\012/", file_get_contents($src));
217 $info = pathinfo($file);
218 if (isset($info['extension'])) {
219 foreach ($mimes as $mime) {
220 if ('#' != substr($mime, 0, 1)) {
221 $elts = preg_split('/ |\t/', $mime, -1, PREG_SPLIT_NO_EMPTY);
222 if (in_array($info['extension'], $elts)) {
223 return array($elts[0], $info['basename']);
224 }
225 }
226 }
227 } else {
228 // we consider that if no extension and base name is all
229 // uppercase, then we have a text file.
230 if ($info['basename'] == strtoupper($info['basename'])) {
231 return array('text/plain', $info['basename']);
232 }
233 }
234 return array('application/octet-stream', $info['basename']);
235 }
236}
237
238function IDF_Views_Source_PrettySize($size)
239{
240 return Pluf_Template::markSafe(Pluf_Utils::prettySize($size));
241}
242
243

Archive Download this file