return null;
}
+ private static function parse_difftree($line) {
+ $entry = array();
+ if(preg_match('/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/i', $line, $matches)) {
+ $entry['parents'] = 1;
+ $entry['from_mode'] = $matches[1];
+ $entry['to_mode'] = $matches[2];
+ $entry['from_id'] = $matches[3];
+ $entry['to_id'] = $matches[4];
+ $entry['status'] = $matches[5];
+ $entry['similarity'] = $matches[6];
+ $entry['file'] = $matches[7];
+ if($entry['status'] == 'R' || $entry['status'] == 'C') { //renamed or copied
+ $files = explode("\t", $entry['file']);
+ $entry['from_file'] = $files[0];
+ $entry['to_file'] = $files[1];
+ }
+ } else if(preg_match('/^(::+)((?:[0-7]{6} )+)((?:[0-9a-fA-F]{40} )+)([a-zA-Z]+)\t(.*)$/i', $line, $matches)) {
+ $entry['parents'] = strlen($matches[1]);
+ $from_modes = explode(" ", $matches[2]);
+ $entry['from_mode'] = array_slice($from_modes, 1);
+ $entry['to_mode'] = $from_modes[0];
+ $from_ids = explode(" ", $matches[3]);
+ $entry['from_id'] = array_slice($from_ids, 1);
+ $entry['to_id'] = $from_ids[0];
+ $entry['status'] = str_split($matches[4]);
+ $entry['file'] = $matches[5];
+ }
+ return $entry;
+ }
+
public static function get_commit_changes($git_path, $commit_id, $parents) {
$args = array("diff-tree", "-r", "--no-commit-id");
switch(GitConfig::DETECT_RENAME_LEVEL) {
foreach(explode("\n", $result) as $line) {
if($line == "")
continue;
- $entry = array();
- if(preg_match('/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/i', $line, $matches)) {
- $entry['parents'] = 1;
- $entry['from_mode'] = $matches[1];
- $entry['to_mode'] = $matches[2];
- $entry['from_id'] = $matches[3];
- $entry['to_id'] = $matches[4];
- $entry['status'] = $matches[5];
- $entry['similarity'] = $matches[6];
- $entry['file'] = $matches[7];
- if($entry['status'] == 'R' || $entry['status'] == 'C') { //renamed or copied
- $files = explode("\t", $entry['file']);
- $entry['from_file'] = $files[0];
- $entry['to_file'] = $files[1];
- }
- } else if(preg_match('/^(::+)((?:[0-7]{6} )+)((?:[0-9a-fA-F]{40} )+)([a-zA-Z]+)\t(.*)$/i', $line, $matches)) {
- $entry['parents'] = strlen($matches[1]);
- $from_modes = explode(" ", $matches[2]);
- $entry['from_mode'] = array_slice($from_modes, 1);
- $entry['to_mode'] = $from_modes[0];
- $from_ids = explode(" ", $matches[3]);
- $entry['from_id'] = array_slice($from_ids, 1);
- $entry['to_id'] = $from_ids[0];
- $entry['status'] = str_split($matches[4]);
- $entry['file'] = $matches[5];
- }
- $tree[] = $entry;
+ $tree[] = self::parse_difftree($line);
}
return $tree;
}
+ public static function get_commit_diff($git_path, $commit_id, $parents) {
+ $args = array("diff-tree", "-r", "--no-commit-id", "--patch-with-raw", "--full-index");
+ switch(GitConfig::DETECT_RENAME_LEVEL) {
+ case 0:
+ $args[] = "-M";
+ break;
+ case 1:
+ $args[] = "-C";
+ break;
+ case 2:
+ $args[] = "-C";
+ $args[] = "--find-copies-harder";
+ break;
+ }
+ if(GitConfig::DETECT_REWRITES)
+ $args[] = "-B";
+ if(is_array($parents) && count($parents) > 1)
+ $args[] = "--cc";
+ else if(is_array($parents) && count($parents) == 1)
+ $args[] = $parents[0];
+ else
+ $args[] = "--root";
+ $args[] = $commit_id;
+ $args[] = "--";
+ $result = self::git_execute($args, $git_path);
+ $tree = array();
+ $diffs = array();
+ $diff = null;
+ $parse_difftree = true;
+ foreach(explode("\n", $result) as $line) {
+ if($line == "" && $parse_difftree)
+ $parse_difftree = false;
+ else if($parse_difftree)
+ $tree[] = self::parse_difftree($line);
+ else {
+ if(preg_match('/^diff/i', $line)) {
+ if($diff)
+ $diffs[] = $diff;
+ $diff = array();
+ }
+ $diff[] = $line;
+ }
+ }
+ if($diff)
+ $diffs[] = $diff;
+ $diff_data['tree'] = $tree;
+ return array('tree' => $tree, 'diffs' => $diffs);
+ }
}
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-require_once('pages/shortlog.class.php');
-
class difftree {
+ private $difftree_data = null;
+
+ public function push_difftree_data($data) {
+ $this->difftree_data = $data;
+ }
public function generate_difftree($project, $commit, $patch_link) {
$difftree = new ContentProvider('commit', 'difftree');
- $tree = GitCommand::get_commit_changes($project['path'], $commit['id'], $commit['parent']);
+ if($this->difftree_data)
+ $tree = $this->difftree_data;
+ else
+ $tree = GitCommand::get_commit_changes($project['path'], $commit['id'], $commit['parent']);
$entry_count = 0;
if(count($commit['parent']) > 1)
$difftree->set('class', ' combined');
else
$difftree->set('class', '');
+ $difftree->set('tree_count', '');
foreach($tree as $entry) {
$entry_count++;
$difftree->append('tree', $this->tree_entry($entry_count, (($entry_count % 2) ? 'dark' : 'light'), $commit, $entry, $patch_link));
}
- if(count($tree) == 0)
+ if($entry_count == 0)
$difftree->set('tree', '');
+ else if($entry_count > 10)
+ $difftree->set('tree_count', new ContentProvider('commit', 'tree_count', array('count' => $entry_count)));
return $difftree;
}
}
} else
$tree->set('specials', '');
- if($entry['from_id'] != $entry['to_id'])
+ if(!$patch_link && $entry['from_id'] != $entry['to_id'])
$tree->append('links', new ContentProvider('commit', 'tree_changed_links_diff', $link_placeholders));
$tree->append('links', new ContentProvider('commit', 'tree_changed_links', $link_placeholders));
break;
else
$this->page->set('committer_local_date', gmdate('H:i', $committer_local_time));
$this->page->set('committer_timezone', $commit['committer_timezone']);
- $this->page->set('message', htmlentities(Tools::chop_text($commit['text'], 50, 5)));
+ $this->page->set('message', htmlentities(Tools::chop_text($commit['text'], 80, 5)));
$this->page->set('full_message', htmlentities($commit['text']));
$this->page->set('tree_hash', $commit['tree']);
foreach($commit['parent'] as $parent) {
--- /dev/null
+<?php
+/* commitdiff.class.php - phpgitweb
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+require_once("pages/commit.class.php");
+
+class page_commitdiff {
+ private $page, $phpgitweb;
+ private $commitid;
+
+ public function main($phpgitweb, $project) {
+ $this->phpgitweb = $phpgitweb;
+ if(!$project)
+ return new ContentProvider('main', 'err400');
+ $project['refs'] = $phpgitweb->get_project_loader()->getProjectRefs($project);
+ $phpgitweb->append_header_nav("commit", null, true);
+ $phpgitweb->append_title("commit");
+
+ $commit_loader = new CommitLoader($project);
+
+ if(array_key_exists('h', $_GET))
+ $commitid = $_GET['h'];
+ else
+ $commitid = "HEAD";
+
+ $commit = $commit_loader->load($commitid);
+ if(!$commit)
+ return new ContentProvider('main', 'err404_object');
+
+ ContentProvider::overall_set('project_head', $commit['id']);
+
+
+ $this->page = new ContentProvider('commitdiff', 'main');
+ $this->page->set('hash', $commit['id']);
+ $this->page->set('author', htmlentities($commit['author']));
+ $this->page->set('author_mail', htmlentities($commit['author_mail']));
+ $this->page->set('author_date', gmdate('r', $commit['author_time']));
+ $author_local_time = $commit['author_time'] + Tools::parseTimeZone($commit['author_timezone']);
+ if(gmdate('H', $author_local_time) < 6)
+ $this->page->set('author_local_date', '<span class="atnight">'.gmdate('H:i', $author_local_time).'</span>');
+ else
+ $this->page->set('author_local_date', gmdate('H:i', $author_local_time));
+ $this->page->set('author_timezone', $commit['author_timezone']);
+ $this->page->set('committer', htmlentities($commit['committer']));
+ $this->page->set('committer_mail', htmlentities($commit['committer_mail']));
+ $this->page->set('committer_date', gmdate('r', $commit['committer_time']));
+ $committer_local_time = $commit['committer_time'] + Tools::parseTimeZone($commit['committer_timezone']);
+ if(gmdate('H', $committer_local_time) < 6)
+ $this->page->set('committer_local_date', '<span class="atnight">'.gmdate('H:i', $committer_local_time).'</span>');
+ else
+ $this->page->set('committer_local_date', gmdate('H:i', $committer_local_time));
+ $this->page->set('committer_timezone', $commit['committer_timezone']);
+ $this->page->set('message', htmlentities(Tools::chop_text($commit['text'], 80, 5)));
+
+
+ $refs = new ContentProvider('commit', 'commit_refs');
+ $found = false;
+ foreach($project['refs'] as $ref => $rhash) {
+ if(strtolower($rhash) == strtolower($commit['id'])) {
+ $refexp = explode('/', $ref, 3);
+ $reftype = $refexp[1];
+ if($reftype == 'heads')
+ $reftype = 'head';
+ else if($reftype == 'remotes')
+ $reftype = 'remote';
+ else if($reftype == 'tags')
+ $reftype = 'tag';
+ $refs->append('refs', new ContentProvider('commit', 'commit_ref_'.$reftype, array("name" => $refexp[2], "ref_link" => $ref)));
+ $found = true;
+ }
+ }
+ $this->page->set('refs', ($found ? $refs : ""));
+
+ $difftree = new difftree();
+ $diff_data = GitCommand::get_commit_diff($project['path'], $commit['id'], $commit['parent']);
+ $difftree->push_difftree_data($diff_data['tree']);
+ $this->page->set('difftree', $difftree->generate_difftree($project, $commit, true));
+
+
+
+ return $this->page;
+ }
+}
+
+?>
\ No newline at end of file
<div class="page_body">
%full_message%<br/>
</div>
-
-<div class="list_head">
-</div>
%difftree%
<td class="sha1"><a class="list" href="?p=%project%&a=commit&h=%hash%">%hash%</a></td>
<td class="link">
<a href="?p=%project%&a=commit&h=%hash%">commit</a> |
- <a href="?p=%project%&a=commitdiff&h=%head%;hp=%hash%">diff</a>
+ <a href="?p=%project%&a=commitdiff&h=%head%&hp=%hash%">diff</a>
</td>
</tr>
<span class="tag" title="tags/%name%">%name%</span>
# [difftree]
+<div class="list_head">
+%tree_count%
+</div>
<table class="diff_tree%class%">
%tree%
</table>
+# [tree_count]
+%count% files changed:
+
# [tree]
<tr class="%class%">
<td>%file%</td>
--- /dev/null
+# [main]
+<div class="header">
+<a class="title" href="?p=%project%&a=commitdiff&h=%hash%">%message% %refs%</a>
+</div>
+<div class="title_text">
+<table class="object_header">
+ <tr>
+ <td>author</td>
+ <td>
+ <a title="Search for commits authored by %author%" class="list" href="?p=%project%&a=search&h=%hash%&s=%author%&st=author">%author%</a>
+ <a title="Search for commits authored by %author_mail%" class="list" href="?p=%project%&a=search&h=%hash%&s=%author_mail%&st=author"><%author_mail%></a>
+ </td>
+ <td rowspan="2"></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td> %author_date% (%author_local_date% %author_timezone%)</td>
+ </tr>
+ <tr>
+ <td>committer</td>
+ <td>
+ <a title="Search for commits committed by %committer%" class="list" href="?p=%project%&a=search&h=%hash%&s=pk910&st=committer">%committer%</a>
+ <a title="Search for commits committed by %committer_mail%" class="list" href="?p=%project%&a=search&h=%hash%&s=%committer_mail%&st=committer"><%committer_mail%></a>
+ </td>
+ <td rowspan="2"></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td> %committer_date% (%committer_local_date% %committer_timezone%)</td>
+ </tr>
+</table>
+</div>
+<div class="page_body">
+%difftree%
+<br/>
+<div class="patchset">
+%patchset%
+</div>
+</div>
\ No newline at end of file
</div>
# [project_header_nav_link]
-<a href="/?p=%project%&a=%link%">%name%</a>
+<a href="/?p=%project%&a=%link%&h=%project_head%">%name%</a>
# [project_header_nav_active]
%name%