.
*/
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');
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($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;
}
private function tree_entry($diffid, $class, $commit, $entry, $patch_link) {
$tree = new ContentProvider('commit', 'tree');
$tree->set('class', $class);
$tree->set('hash', $commit['id']);
$tree->set('file', $entry['file']);
if(count($commit['parent']) > 1) {
if(preg_match('/^[0]{40}$/', $entry['to_id'])) //file doesn't exist in the result (child) commit
$tree->set('file', $entry['file']);
else
$tree->set('file', new ContentProvider('commit', 'tree_file_link', array('file' => $entry['file'])));
$tree->set('specials', '');
if($patch_link)
$tree->append('merge', new ContentProvider('commit', 'tree_merge_patch_link', array("patch_marker" => "patch".$diffid)));
$has_history = false;
$not_deleted = false;
for($i = 0; $i < count($commit['parent']); $i++) {
$status = $entry['status'][$i];
$merge = null;
$has_history = ($has_history || ($status != 'A'));
$not_deleted = ($not_deleted || ($status != 'D'));
switch($status) {
case 'A': //Added
$merge = new ContentProvider('commit', 'tree_merge_new');
break;
case 'D': //Deleted
$merge = new ContentProvider('commit', 'tree_merge');
$merge->set('class', '');
$blob_link = new ContentProvider('commit', 'tree_merge_blob', array('hash' => $commit['parent'][$i], 'file' => $entry['file']));
$merge->set('links', array($blob_link, ' | '));
break;
default:
$merge = new ContentProvider('commit', 'tree_merge');
if($entry['from_id'][$i] == $entry['to_id']) {
$merge->set('class', ' nochange');
$merge->set('links', ' | ');
} else {
$merge->set('class', '');
$merge->set('links', new ContentProvider('commit', 'tree_merge_diff', array('hash' => $commit['id'], 'parent' => $commit['parent'][$i], 'file' => $entry['file'], 'id' => ($i + 1))));
}
}
$tree->append('merge', $merge);
}
$tree->set('links', '');
if($not_deleted) {
$tree->append('links', new ContentProvider('commit', 'tree_merge_blob', array('hash' => $commit['id'], 'file' => $entry['file'])));
if($has_history)
$tree->append('links', ' | ');
}
if($has_history)
$tree->append('links', new ContentProvider('commit', 'tree_merge_history', array('hash' => $commit['id'], 'file' => $entry['file'])));
} else {
$tree->set('file', new ContentProvider('commit', 'tree_file_link', array('file' => $entry['file'])));
$tree->set('merge', '');
$from_type = Tools::get_filetype($entry['from_mode']);
$to_type = Tools::get_filetype($entry['to_mode']);
$from_mode = (Tools::is_regular_file($entry['from_mode']) ? Tools::get_file_permissions($entry['from_mode']) : null);
$to_mode = (Tools::is_regular_file($entry['to_mode']) ? Tools::get_file_permissions($entry['to_mode']) : null);
$link_placeholders = array(
"hash" => $commit['id'],
"file" => $entry['file'],
"parent" => (count($commit['parent']) ? $commit['parent'][0] : ""),
);
if($patch_link)
$tree->append('links', new ContentProvider('commit', 'tree_patch_link', array("patch_marker" => "patch".$diffid)));
switch($entry['status']) {
case 'A': //Added
$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)));
$tree->append('links', new ContentProvider('commit', 'tree_new_links', $link_placeholders));
break;
case 'D': //Deleted
$tree->set('specials', new ContentProvider('commit', 'tree_deleted', array('type' => $from_type)));
$tree->append('links', new ContentProvider('commit', 'tree_deleted_links', $link_placeholders));
break;
case 'M': //Modified
case 'T': //Type changed
if($entry['from_mode'] != $entry['to_mode']) {
$modified = new ContentProvider('commit', 'tree_changed');
$tree->set('specials', $modified);
if($from_type != $to_type)
$modified->append('changes', new ContentProvider('commit', 'tree_changed_type', array('from' => $from_type, 'to' => $to_type)));
if($from_mode != $to_mode && $to_mode) {
if($from_mode)
$modified->append('changes', new ContentProvider('commit', 'tree_changed_mode', array('from' => $from_mode, 'to' => $to_mode)));
else
$modified->append('changes', new ContentProvider('commit', 'tree_changed_mode_to', array('to' => $to_mode)));
}
} else
$tree->set('specials', '');
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;
case 'R': //Renamed
case 'C': //Copied
$actions = array('R' => 'tree_moved', 'C' => 'tree_copied');
$move = new ContentProvider('commit', $actions[$entry['status']]);
$tree->set('specials', $move);
$tree->set('file', $entry['to_file']);
$move->set('file', $entry['from_file']);
$move->set('hash', $commit['parent'][0]);
$move->set('similarity', $entry['similarity']);
if($from_mode != $to_mode)
$move->set('mode', new ContentProvider('commit', 'tree_moved_mode', array('mode' => $to_mode)));
else
$move->set('mode', '');
if($entry['from_id'] != $entry['to_id'])
$tree->append('links', new ContentProvider('commit', 'tree_moved_links_diff', $link_placeholders));
$tree->append('links', new ContentProvider('commit', 'tree_moved_links', $link_placeholders));
break;
default:
}
}
return $tree;
}
}
class page_commit {
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('commit', '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', ''.gmdate('H:i', $author_local_time).'');
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', ''.gmdate('H:i', $committer_local_time).'');
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)));
$this->page->set('full_message', htmlentities($commit['text']));
$this->page->set('tree_hash', $commit['tree']);
foreach($commit['parent'] as $parent) {
$this->page->append('parents', new ContentProvider('commit', 'parent', array('hash' => $parent, 'head' => $commit['id'])));
}
if(count($commit['parent']) == 0)
$this->page->set('parents', '');
$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();
$this->page->set('difftree', $difftree->generate_difftree($project, $commit, false));
return $this->page;
}
}
?>