2 /* commit.class.php - phpgitweb
3 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 require_once('pages/shortlog.class.php');
23 public function generate_difftree($project, $commit, $patch_link) {
24 $difftree = new ContentProvider('commit', 'difftree');
25 $tree = GitCommand::get_commit_changes($project['path'], $commit['id'], $commit['parent']);
27 if(count($commit['parent']) > 1)
28 $difftree->set('class', ' combined');
30 $difftree->set('class', '');
31 foreach($tree as $entry) {
33 $difftree->append('tree', $this->tree_entry($entry_count, (($entry_count % 2) ? 'dark' : 'light'), $commit, $entry, $patch_link));
36 $difftree->set('tree', '');
40 private function tree_entry($diffid, $class, $commit, $entry, $patch_link) {
41 $tree = new ContentProvider('commit', 'tree');
42 $tree->set('class', $class);
43 $tree->set('hash', $commit['id']);
44 $tree->set('file', $entry['file']);
46 if(count($commit['parent']) > 1) {
47 if(preg_match('/^[0]{40}$/', $entry['to_id'])) //file doesn't exist in the result (child) commit
48 $tree->set('file', $entry['file']);
50 $tree->set('file', new ContentProvider('commit', 'tree_file_link', array('file' => $entry['file'])));
52 $tree->set('specials', '');
55 $tree->append('merge', new ContentProvider('commit', 'tree_merge_patch_link', array("patch_marker" => "patch".$diffid)));
60 for($i = 0; $i < count($commit['parent']); $i++) {
61 $status = $entry['status'][$i];
64 $has_history = ($has_history || ($status != 'A'));
65 $not_deleted = ($not_deleted || ($status != 'D'));
69 $merge = new ContentProvider('commit', 'tree_merge_new');
72 $merge = new ContentProvider('commit', 'tree_merge');
73 $merge->set('class', '');
74 $blob_link = new ContentProvider('commit', 'tree_merge_blob', array('hash' => $commit['parent'][$i], 'file' => $entry['file']));
75 $merge->set('links', array($blob_link, ' | '));
78 $merge = new ContentProvider('commit', 'tree_merge');
79 if($entry['from_id'][$i] == $entry['to_id']) {
80 $merge->set('class', ' nochange');
81 $merge->set('links', ' | ');
83 $merge->set('class', '');
84 $merge->set('links', new ContentProvider('commit', 'tree_merge_diff', array('hash' => $commit['id'], 'parent' => $commit['parent'][$i], 'file' => $entry['file'], 'id' => ($i + 1))));
87 $tree->append('merge', $merge);
90 $tree->set('links', '');
92 $tree->append('links', new ContentProvider('commit', 'tree_merge_blob', array('hash' => $commit['id'], 'file' => $entry['file'])));
94 $tree->append('links', ' | ');
97 $tree->append('links', new ContentProvider('commit', 'tree_merge_history', array('hash' => $commit['id'], 'file' => $entry['file'])));
100 $tree->set('file', new ContentProvider('commit', 'tree_file_link', array('file' => $entry['file'])));
101 $tree->set('merge', '');
103 $from_type = Tools::get_filetype($entry['from_mode']);
104 $to_type = Tools::get_filetype($entry['to_mode']);
106 $from_mode = (Tools::is_regular_file($entry['from_mode']) ? Tools::get_file_permissions($entry['from_mode']) : null);
107 $to_mode = (Tools::is_regular_file($entry['to_mode']) ? Tools::get_file_permissions($entry['to_mode']) : null);
109 $link_placeholders = array(
110 "hash" => $commit['id'],
111 "file" => $entry['file'],
112 "parent" => (count($commit['parent']) ? $commit['parent'][0] : ""),
115 $tree->append('links', new ContentProvider('commit', 'tree_patch_link', array("patch_marker" => "patch".$diffid)));
117 switch($entry['status']) {
119 $tree->set('specials', new ContentProvider('commit', (Tools::is_regular_file($entry['to_mode']) ? 'tree_new_file' : 'tree_new'), array('type' => $to_type, 'mode' => $to_mode)));
120 $tree->append('links', new ContentProvider('commit', 'tree_new_links', $link_placeholders));
123 $tree->set('specials', new ContentProvider('commit', 'tree_deleted', array('type' => $from_type)));
124 $tree->append('links', new ContentProvider('commit', 'tree_deleted_links', $link_placeholders));
127 case 'T': //Type changed
128 if($entry['from_mode'] != $entry['to_mode']) {
129 $modified = new ContentProvider('commit', 'tree_changed');
130 $tree->set('specials', $modified);
131 if($from_type != $to_type)
132 $modified->append('changes', new ContentProvider('commit', 'tree_changed_type', array('from' => $from_type, 'to' => $to_type)));
133 if($from_mode != $to_mode && $to_mode) {
135 $modified->append('changes', new ContentProvider('commit', 'tree_changed_mode', array('from' => $from_mode, 'to' => $to_mode)));
137 $modified->append('changes', new ContentProvider('commit', 'tree_changed_mode_to', array('to' => $to_mode)));
140 $tree->set('specials', '');
141 if($entry['from_id'] != $entry['to_id'])
142 $tree->append('links', new ContentProvider('commit', 'tree_changed_links_diff', $link_placeholders));
143 $tree->append('links', new ContentProvider('commit', 'tree_changed_links', $link_placeholders));
147 $actions = array('R' => 'tree_moved', 'C' => 'tree_copied');
148 $move = new ContentProvider('commit', $actions[$entry['status']]);
149 $tree->set('specials', $move);
150 $tree->set('file', $entry['to_file']);
151 $move->set('file', $entry['from_file']);
152 $move->set('hash', $commit['parent'][0]);
153 $move->set('similarity', $entry['similarity']);
154 if($from_mode != $to_mode)
155 $move->set('mode', new ContentProvider('commit', 'tree_moved_mode', array('mode' => $to_mode)));
157 $move->set('mode', '');
158 if($entry['from_id'] != $entry['to_id'])
159 $tree->append('links', new ContentProvider('commit', 'tree_moved_links_diff', $link_placeholders));
160 $tree->append('links', new ContentProvider('commit', 'tree_moved_links', $link_placeholders));
173 private $page, $phpgitweb;
176 public function main($phpgitweb, $project) {
177 $this->phpgitweb = $phpgitweb;
179 return new ContentProvider('main', 'err400');
180 $project['refs'] = $phpgitweb->get_project_loader()->getProjectRefs($project);
181 $phpgitweb->append_header_nav("commit", null, true);
182 $phpgitweb->append_title("commit");
184 $commit_loader = new CommitLoader($project);
186 if(array_key_exists('h', $_GET))
187 $commitid = $_GET['h'];
191 $commit = $commit_loader->load($commitid);
193 return new ContentProvider('main', 'err404_object');
195 ContentProvider::overall_set('project_head', $commit['id']);
198 $this->page = new ContentProvider('commit', 'main');
199 $this->page->set('hash', $commit['id']);
200 $this->page->set('author', htmlentities($commit['author']));
201 $this->page->set('author_mail', htmlentities($commit['author_mail']));
202 $this->page->set('author_date', gmdate('r', $commit['author_time']));
203 $author_local_time = $commit['author_time'] + Tools::parseTimeZone($commit['author_timezone']);
204 if(gmdate('H', $author_local_time) < 6)
205 $this->page->set('author_local_date', '<span class="atnight">'.gmdate('H:i', $author_local_time).'</span>');
207 $this->page->set('author_local_date', gmdate('H:i', $author_local_time));
208 $this->page->set('author_timezone', $commit['author_timezone']);
209 $this->page->set('committer', htmlentities($commit['committer']));
210 $this->page->set('committer_mail', htmlentities($commit['committer_mail']));
211 $this->page->set('committer_date', gmdate('r', $commit['committer_time']));
212 $committer_local_time = $commit['committer_time'] + Tools::parseTimeZone($commit['committer_timezone']);
213 if(gmdate('H', $committer_local_time) < 6)
214 $this->page->set('committer_local_date', '<span class="atnight">'.gmdate('H:i', $committer_local_time).'</span>');
216 $this->page->set('committer_local_date', gmdate('H:i', $committer_local_time));
217 $this->page->set('committer_timezone', $commit['committer_timezone']);
218 $this->page->set('message', htmlentities(Tools::chop_text($commit['text'], 50, 5)));
219 $this->page->set('full_message', htmlentities($commit['text']));
220 $this->page->set('tree_hash', $commit['tree']);
221 foreach($commit['parent'] as $parent) {
222 $this->page->append('parents', new ContentProvider('commit', 'parent', array('hash' => $parent, 'head' => $commit['id'])));
224 if(count($commit['parent']) == 0)
225 $this->page->set('parents', '');
227 $refs = new ContentProvider('commit', 'commit_refs');
229 foreach($project['refs'] as $ref => $rhash) {
230 if(strtolower($rhash) == strtolower($commit['id'])) {
231 $refexp = explode('/', $ref, 3);
232 $reftype = $refexp[1];
233 if($reftype == 'heads')
235 else if($reftype == 'remotes')
237 else if($reftype == 'tags')
239 $refs->append('refs', new ContentProvider('commit', 'commit_ref_'.$reftype, array("name" => $refexp[2], "ref_link" => $ref)));
243 $this->page->set('refs', ($found ? $refs : ""));
245 $difftree = new difftree();
246 $this->page->set('difftree', $difftree->generate_difftree($project, $commit, false));