RSS item title/description is configurable now.
[viewgit.git] / index.php
blob611f963da37b6ef3feb13afba741ad0339d20cbb
1 <?php
2 /** @file
3 * The main "controller" file of ViewGit.
5 * All requests come to this file. You can think of it as the controller in the
6 * Model-View-Controller pattern. It reads config, processes user input,
7 * fetches required data using git commandline, and finally passes the data to
8 * templates to be shown to the user.
9 */
10 error_reporting(E_ALL);
12 require_once('inc/config.php');
13 require_once('inc/functions.php');
15 $action = 'index';
16 $template = 'index';
17 $page['title'] = 'ViewGit';
19 if (isset($_REQUEST['a'])) {
20 $action = strtolower($_REQUEST['a']);
22 $page['action'] = $action;
24 if ($action === 'index') {
25 $template = 'index';
26 $page['title'] = 'List of projects - ViewGit';
28 foreach (array_keys($conf['projects']) as $p) {
29 $page['projects'][] = get_project_info($p);
32 elseif ($action === 'archive') {
33 $project = validate_project($_REQUEST['p']);
34 $tree = validate_hash($_REQUEST['h']);
35 $type = $_REQUEST['t'];
37 $basename = "$project-tree-". substr($tree, 0, 7);
38 if (isset($_REQUEST['n'])) {
39 $basename = "$project-$_REQUEST[n]-". substr($tree, 0, 6);
42 if ($type === 'targz') {
43 header("Content-Type: application/x-tar-gz");
44 header("Content-Transfer-Encoding: binary");
45 header("Content-Disposition: attachment; filename=\"$basename.tar.gz\";");
46 run_git_passthru($project, "git archive --format=tar $tree |gzip");
48 elseif ($type === 'zip') {
49 header("Content-Type: application/x-zip");
50 header("Content-Transfer-Encoding: binary");
51 header("Content-Disposition: attachment; filename=\"$basename.zip\";");
52 run_git_passthru($project, "git archive --format=zip $tree");
54 else {
55 die('Invalid archive type requested');
58 die();
60 // blob: send a blob to browser with filename suggestion
61 elseif ($action === 'blob') {
62 $project = validate_project($_REQUEST['p']);
63 $hash = validate_hash($_REQUEST['h']);
64 $name = $_REQUEST['n'];
66 header('Content-type: application/octet-stream');
67 header("Content-Disposition: attachment; filename=$name"); // FIXME needs quotation
69 run_git_passthru($project, "git cat-file blob $hash");
70 die();
72 /**
73 * git checkout.
75 elseif ($action === 'co') {
76 if (!$conf['allow_checkout']) { die('Checkout not allowed'); }
78 // For debugging
79 debug("Project: $_REQUEST[p] Request: $_REQUEST[r]");
81 // eg. info/refs, HEAD
82 $p = validate_project($_REQUEST['p']); // project
83 $r = $_REQUEST['r']; // path
85 $gitdir = $conf['projects'][$p]['repo'];
86 $filename = $gitdir .'/'. $r;
88 // make sure the request is legit (no reading of other files besides those under git projects)
89 if ($r === 'HEAD' || $r === 'info/refs' || preg_match('!^objects/info/(packs|http-alternates|alternates)$!', $r) > 0 || preg_match('!^objects/[0-9a-f]{2}/[0-9a-f]{38}$!', $r) > 0) {
90 if (file_exists($filename)) {
91 debug('OK, sending');
92 readfile($filename);
93 } else {
94 debug('Not found');
95 header('404');
97 } else {
98 debug("Denied");
101 die();
103 elseif ($action === 'commit') {
104 $template = 'commit';
105 $page['project'] = validate_project($_REQUEST['p']);
106 $page['title'] = "$page[project] - Commit - ViewGit";
107 $page['commit_id'] = validate_hash($_REQUEST['h']);
109 $info = git_get_commit_info($page['project'], $page['commit_id']);
111 $page['author_name'] = $info['author_name'];
112 $page['author_mail'] = $info['author_mail'];
113 $page['author_datetime'] = strftime($conf['datetime'], $info['author_utcstamp']);
114 $page['author_datetime_local'] = strftime($conf['datetime'], $info['author_stamp']) .' '. $info['author_timezone'];
115 $page['committer_name'] = $info['committer_name'];
116 $page['committer_mail'] = $info['committer_mail'];
117 $page['committer_datetime'] = strftime($conf['datetime'], $info['committer_utcstamp']);
118 $page['committer_datetime_local'] = strftime($conf['datetime'], $info['committer_stamp']) .' '. $info['committer_timezone'];
119 $page['tree_id'] = $info['tree'];
120 $page['parents'] = $info['parents'];
121 $page['message'] = $info['message'];
122 $page['message_firstline'] = $info['message_firstline'];
123 $page['message_full'] = $info['message_full'];
126 elseif ($action === 'commitdiff') {
127 $template = 'commitdiff';
128 $page['project'] = validate_project($_REQUEST['p']);
129 $page['title'] = "$page[project] - Commitdiff - ViewGit";
130 $hash = validate_hash($_REQUEST['h']);
131 $page['commit_id'] = $hash;
133 $info = git_get_commit_info($page['project'], $hash);
135 $page['tree_id'] = $info['tree'];
137 $page['message'] = $info['message'];
138 $page['message_firstline'] = $info['message_firstline'];
139 $page['message_full'] = $info['message_full'];
140 $page['author_name'] = $info['author_name'];
141 $page['author_mail'] = $info['author_mail'];
142 $page['author_datetime'] = strftime($conf['datetime'], $info['author_utcstamp']);
144 $text = join("\n", run_git($page['project'], "git diff $hash^..$hash"));
145 list($page['files'], $page['diffdata']) = format_diff($text);
146 //$page['diffdata'] = format_diff($text);
148 elseif ($action === 'rss-log') {
149 $page['project'] = validate_project($_REQUEST['p']);
151 $ext_url = 'http://'. $_SERVER['HTTP_HOST'] . dirname($_SERVER['SCRIPT_NAME']) .'/';
153 $page['rss_title'] = "Log for $page[project]";
154 $page['rss_link'] = $ext_url . makelink(array('a' => 'summary', 'p' => $page['project']));
155 $page['rss_description'] = "Git log for project $page[project], generated by ViewGit.";
156 $page['rss_pubDate'] = rss_pubdate(time());
157 $page['rss_ttl'] = $conf['rss_ttl'];
159 $page['rss_items'] = array();
161 $revs = git_get_rev_list($page['project'], $conf['rss_max_items']);
162 foreach ($revs as $rev) {
163 $info = git_get_commit_info($page['project'], $rev);
164 $link = $ext_url . makelink(array('a' => 'commit', 'p' => $page['project'], 'h' => $rev));
166 $page['rss_items'][] = array(
167 'title' => rss_item_format($conf['rss_item_title'], $info),
168 'guid' => $link,
169 'link' => $link,
170 'description' => rss_item_format($conf['rss_item_description'], $info),
171 'pubdate' => rss_pubdate($info['author_stamp']),
175 require('templates/rss.php');
176 die();
178 elseif ($action === 'shortlog') {
179 $template = 'shortlog';
180 $page['project'] = validate_project($_REQUEST['p']);
181 $page['title'] = "$page[project] - Shortlog - ViewGit";
182 if (isset($_REQUEST['h'])) {
183 $page['ref'] = validate_hash($_REQUEST['h']);
184 } else {
185 $page['ref'] = 'HEAD';
188 $info = git_get_commit_info($page['project'], $page['ref']);
189 $page['commit_id'] = $info['h'];
190 $page['tree_id'] = $info['tree'];
192 // TODO merge the logic with 'summary' below
193 $revs = git_get_rev_list($page['project'], $conf['summary_shortlog'], $page['ref']); // TODO pass first rev as parameter
194 foreach ($revs as $rev) {
195 $info = git_get_commit_info($page['project'], $rev);
196 $page['shortlog'][] = array(
197 'author' => $info['author_name'],
198 'date' => strftime($conf['datetime'], $info['author_utcstamp']),
199 'message' => $info['message'],
200 'commit_id' => $rev,
201 'tree' => $info['tree'],
205 elseif ($action === 'summary') {
206 $template = 'summary';
207 $page['project'] = validate_project($_REQUEST['p']);
208 $page['title'] = "$page[project] - Summary - ViewGit";
210 $info = git_get_commit_info($page['project']);
211 $page['commit_id'] = $info['h'];
212 $page['tree_id'] = $info['tree'];
214 $revs = git_get_rev_list($page['project'], $conf['summary_shortlog']);
215 foreach ($revs as $rev) {
216 $info = git_get_commit_info($page['project'], $rev);
217 $page['shortlog'][] = array(
218 'author' => $info['author_name'],
219 'date' => strftime($conf['datetime'], $info['author_utcstamp']),
220 'message' => $info['message'],
221 'commit_id' => $rev,
222 'tree' => $info['tree'],
226 $tags = git_get_tags($page['project']);
227 $page['tags'] = array();
228 foreach ($tags as $tag) {
229 $info = git_get_commit_info($page['project'], $tag['h']);
230 $page['tags'][] = array(
231 'stamp' => $info['author_utcstamp'],
232 'date' => strftime($conf['datetime'], $info['author_utcstamp']),
233 'h' => $tag['h'],
234 'fullname' => $tag['fullname'],
235 'name' => $tag['name'],
238 // sort tags newest first
239 // aka. two more reasons to hate PHP (figuring those out is your homework:)
240 $arr = $page['tags'];
241 usort($arr, create_function(
242 '$x, $y',
243 '$a = $x["stamp"]; $b = $y["stamp"]; return ($a == $b ? 0 : ($a > $b ? -1 : 1));'
245 // it's actually three, I lied.
246 $page['tags'] = $arr;
248 $heads = git_get_heads($page['project']);
249 $page['heads'] = array();
250 foreach ($heads as $h) {
251 $info = git_get_commit_info($page['project'], $h['h']);
252 $page['heads'][] = array(
253 'date' => strftime($conf['datetime'], $info['author_utcstamp']),
254 'h' => $h['h'],
255 'fullname' => $h['fullname'],
256 'name' => $h['name'],
261 * Shows a tree, with list of directories/files, links to them and download
262 * links to archives.
264 * @param p project
265 * @param h tree hash
266 * @param hb OPTIONAL base commit (trees can be part of multiple commits, this
267 * one denotes which commit the user navigated from)
268 * @param f OPTIONAL path the user has followed to view this tree
270 elseif ($action === 'tree') {
271 $template = 'tree';
272 $page['project'] = validate_project($_REQUEST['p']);
273 $page['tree_id'] = validate_hash($_REQUEST['h']);
274 $page['title'] = "$page[project] - Tree - ViewGit";
276 // 'hb' optionally contains the commit_id this tree is related to
277 if (isset($_REQUEST['hb'])) {
278 $page['commit_id'] = validate_hash($_REQUEST['hb']);
280 else {
281 // for the header
282 $info = git_get_commit_info($page['project']);
283 $page['commit_id'] = $info['h'];
286 $page['path'] = '';
287 if (isset($_REQUEST['f'])) {
288 $page['path'] = $_REQUEST['f']; // TODO validate?
291 // get path info for the header
292 $page['pathinfo'] = git_get_path_info($page['project'], $page['commit_id'], explode('/', $page['path']));
294 $page['entries'] = git_ls_tree($page['project'], $page['tree_id']);
297 * View a blob as inline, embedded on the page.
298 * @param p project
299 * @param h blob hash
300 * @param hb OPTIONAL base commit
302 elseif ($action === 'viewblob') {
303 $template = 'blob';
304 $page['project'] = validate_project($_REQUEST['p']);
305 $page['hash'] = validate_hash($_REQUEST['h']);
306 $page['title'] = "$page[project] - Blob - ViewGit";
307 if (isset($_REQUEST['hb'])) {
308 $page['commit_id'] = validate_hash($_REQUEST['hb']);
310 else {
311 $page['commit_id'] = 'HEAD';
314 $page['path'] = '';
315 if (isset($_REQUEST['f'])) {
316 $page['path'] = $_REQUEST['f']; // TODO validate?
319 // For the header's pagenav
320 $info = git_get_commit_info($page['project'], $page['commit_id']);
321 $page['commit_id'] = $info['h'];
322 $page['tree_id'] = $info['tree'];
324 $page['pathinfo'] = git_get_path_info($page['project'], $page['commit_id'], explode('/', $page['path']));
326 $page['data'] = join("\n", run_git($page['project'], "git cat-file blob $page[hash]"));
328 else {
329 die('Invalid action');
332 require 'templates/header.php';
333 require "templates/$template.php";
334 require 'templates/footer.php';