From: pk910 Date: Thu, 14 Feb 2013 07:19:34 +0000 (+0100) Subject: finished graphs X-Git-Url: http://git.pk910.de/?p=phpgitweb.git;a=commitdiff_plain;h=bb1fc2c20c1ec39257c6e89cae030636c15edad3;hp=0a6d29345b57ef71b076003e18d13efd3478764c finished graphs --- diff --git a/htdocs/config.example.php b/htdocs/config.example.php index f333278..6b3bdc4 100644 --- a/htdocs/config.example.php +++ b/htdocs/config.example.php @@ -41,11 +41,22 @@ class GitConfig { /* Override Project Owner to this one */ const PROJECT_OWNER = NULL; + /* Git Base URL (The URL where all the repositories can be cloned from.) */ + //static public $GIT_BASE_URL = NULL; + static public $GIT_BASE_URL = array("git://git.example.net"); + /* Template name */ const TEMPLATE_NAME = NULL; /* Git executable */ const GIT_EXEC = NULL; /* autodetect */ + + /* GIT Graphs */ + const GITGRAPH_ENABLE = true; + const GITGRAPH_MAX_BRANCHES = 20; + const GITGRAPH_END_SIZE = 20; + const GITGRAPH_TILE_SIZE = 20; + const GITGRAPH_BASE64 = true; } ?> \ No newline at end of file diff --git a/htdocs/img/branch_left.png b/htdocs/img/branch_left.png deleted file mode 100644 index 06016a1..0000000 Binary files a/htdocs/img/branch_left.png and /dev/null differ diff --git a/htdocs/img/branch_right.png b/htdocs/img/branch_right.png deleted file mode 100644 index 1db9a66..0000000 Binary files a/htdocs/img/branch_right.png and /dev/null differ diff --git a/htdocs/img/dot.png b/htdocs/img/dot.png deleted file mode 100644 index 433e75a..0000000 Binary files a/htdocs/img/dot.png and /dev/null differ diff --git a/htdocs/img/dot_init.png b/htdocs/img/dot_init.png deleted file mode 100644 index 5fbde45..0000000 Binary files a/htdocs/img/dot_init.png and /dev/null differ diff --git a/htdocs/img/dot_merge.png b/htdocs/img/dot_merge.png deleted file mode 100644 index 70691d0..0000000 Binary files a/htdocs/img/dot_merge.png and /dev/null differ diff --git a/htdocs/img/dot_merge_left.png b/htdocs/img/dot_merge_left.png deleted file mode 100644 index 0fa7c87..0000000 Binary files a/htdocs/img/dot_merge_left.png and /dev/null differ diff --git a/htdocs/img/dot_merge_right.png b/htdocs/img/dot_merge_right.png deleted file mode 100644 index 8ccef25..0000000 Binary files a/htdocs/img/dot_merge_right.png and /dev/null differ diff --git a/htdocs/img/line.png b/htdocs/img/line.png deleted file mode 100644 index 1358887..0000000 Binary files a/htdocs/img/line.png and /dev/null differ diff --git a/htdocs/img/line_h.png b/htdocs/img/line_h.png deleted file mode 100644 index 0585711..0000000 Binary files a/htdocs/img/line_h.png and /dev/null differ diff --git a/htdocs/img/merge_left.png b/htdocs/img/merge_left.png deleted file mode 100644 index cfb950d..0000000 Binary files a/htdocs/img/merge_left.png and /dev/null differ diff --git a/htdocs/img/merge_right.png b/htdocs/img/merge_right.png deleted file mode 100644 index 67e9d32..0000000 Binary files a/htdocs/img/merge_right.png and /dev/null differ diff --git a/htdocs/lib/PHPGitWeb.class.php b/htdocs/lib/PHPGitWeb.class.php index 06ae9b0..8d16d7b 100644 --- a/htdocs/lib/PHPGitWeb.class.php +++ b/htdocs/lib/PHPGitWeb.class.php @@ -49,6 +49,7 @@ class PHPGitWeb { else { ContentProvider::overall_set('project', $this->project['name']); ContentProvider::overall_set('project_head', "HEAD"); + $this->append_header_nav($this->project['name'], '?p='.$this->project['name'].'&a=summary', true); $this->project_header = new ContentProvider('main', 'project_header'); $this->project_header->set('sub_nav', ""); $this->page->append('content', $this->project_header); diff --git a/htdocs/lib/ProjectLoader.class.php b/htdocs/lib/ProjectLoader.class.php index eb1c789..8c0c131 100644 --- a/htdocs/lib/ProjectLoader.class.php +++ b/htdocs/lib/ProjectLoader.class.php @@ -67,6 +67,7 @@ class ProjectLoader { if(strtolower($p['name']) == strtolower($name)) { $found = true; $project['name'] = $p['name']; + $project['owner'] = $p['owner']; break; } } @@ -79,14 +80,16 @@ class ProjectLoader { else $project['description'] = ""; - if(GitConfig::PROJECT_OWNER) - $project['owner'] = GitConfig::PROJECT_OWNER; - else { - $project['owner'] = fileowner($project['path']); - $owner = posix_getpwuid($project['owner']); - if($owner && $owner['name']) - $project['owner'] = $owner['name']; - } + if(!array_key_exists('owner', $project) || $project['owner'] == null) { + if(GitConfig::PROJECT_OWNER) + $project['owner'] = GitConfig::PROJECT_OWNER; + else { + $project['owner'] = fileowner($project['path']); + $owner = posix_getpwuid($project['owner']); + if($owner && $owner['name']) + $project['owner'] = $owner['name']; + } + } return $project; } diff --git a/htdocs/lib/Tools.class.php b/htdocs/lib/Tools.class.php index 8ae0717..d6f9b64 100644 --- a/htdocs/lib/Tools.class.php +++ b/htdocs/lib/Tools.class.php @@ -26,6 +26,7 @@ class Tools { if ($age > 60*60*24*365*2) { $age_str = floor($age/60/60/24/365); $age_str .= " years ago"; + $max_cache = (60*60*24*365) - ($age % (60*60*24*365)); } else if ($age > 60*60*24*(365/12)*2) { $age_str = floor($age/60/60/24/(365/12)); $age_str .= " months ago"; diff --git a/htdocs/lib/graph.class.php b/htdocs/lib/graph.class.php index 5cf843e..53f1aae 100644 --- a/htdocs/lib/graph.class.php +++ b/htdocs/lib/graph.class.php @@ -26,7 +26,7 @@ class graph_data_generator { private $max_branches, $brach_id = 1, $branch_id = 1; public function __construct() { - $this->max_branches = 10; + $this->max_branches = GitConfig::GITGRAPH_MAX_BRANCHES; $this->data['branches'] = array(); $this->data['ubranches'] = array(); } @@ -55,6 +55,8 @@ class graph_data_generator { } public function parse($commits) { + if(!GitConfig::GITGRAPH_ENABLE) + return; $brach_id = $this->brach_id; $branch_uid = $this->branch_id; $first_commit = (count($this->data['branches']) == 0 ? true : false); @@ -113,7 +115,7 @@ class graph_data_generator { for($j = 1; $j < count($commit['parent']); $j++) { $add = true; foreach($this->data['branches'] as $cbranch) { - if($cbranch['next'] == $commit['parent'][$j]) { + if(array_key_exists('next', $cbranch) && $cbranch['next'] == $commit['parent'][$j]) { $add = false; break; } @@ -218,6 +220,8 @@ class graph_data_generator { } public function get_graph($id) { + if(!GitConfig::GITGRAPH_ENABLE) + return; $graph = $this->graph[$id]; $data = $graph['d']['p'].$graph['d']['type'].count($this->data['branches']).'('.implode(',', $graph['l']).')'; $first_merge = true; @@ -231,29 +235,49 @@ class graph_data_generator { } $graph['cs'] = array(); foreach($graph['br'] as $buid) { + if(!$buid) continue; $branch = $this->data['ubranches'][$buid]; - if($branch['pre_merge'] && $branch['pre_merge_start']) + if($branch['pre_merge'] && array_key_exists('pre_merge_start', $branch) && $branch['pre_merge_start']) $graph['cs'][] = $branch['id']."=".$branch['pre_merge_id']; } if(count($graph['cs'])) { $data .= '('.implode(',', $graph['cs']).')'; } + if(GitConfig::GITGRAPH_BASE64) + $data = base64_encode($data); return $data; } + public function get_header_graph() { + $data = "head:"; + $branchcount = 0; + $dataadd = ""; + foreach($this->data['branches'] as $branch) { + if(array_key_exists('sticky', $branch) && $branch['sticky']) { + $name = explode('/', $branch['name'][0], 3); + $dataadd .= "\n".$branch['id'].":".$name[2]; + $branchcount++; + } + } + $data.=$branchcount.$dataadd; + if(GitConfig::GITGRAPH_BASE64) + $data = base64_encode($data); + return $data; + } } class graph_image_generator { - private $max_branches = 10; + private $max_branches; private $image; - private $size = 20; - private $tile_size = 20; + private $size; + private $tile_size; + private $header_height = false; private $colors, $color_swap = array(); - public function generate($data) { - $data = $this->parse_data($data); - if(!$data) - return; + public function __construct() { + $this->max_branches = GitConfig::GITGRAPH_MAX_BRANCHES; + $this->size = GitConfig::GITGRAPH_END_SIZE; + $this->tile_size = GitConfig::GITGRAPH_TILE_SIZE; $this->colors = array( NULL, @@ -265,6 +289,14 @@ class graph_image_generator { array(0, 128, 128), array(128, 0, 128) ); + } + + public function generate($data) { + if(!GitConfig::GITGRAPH_ENABLE) + return; + $data = $this->parse_data($data); + if(!$data) + return; $count = $data['count']; if($count > $this->max_branches) @@ -282,10 +314,50 @@ class graph_image_generator { imagedestroy($this->image); } + private function display_header($header) { + $header = explode("\n",$header); + $count = $header[0]; + $header = array_slice($header, 1); + if($count > $this->max_branches) + $count = $this->max_branches; + if(!$this->header_height) { + $maxlen = 0; + foreach($header as $head) { + $head = explode(":", $head, 2); + $name = $head[1]; + if(strlen($name) > $maxlen) + $maxlen = strlen($name); + } + $this->header_height = $maxlen * 2 + 15; + } + $image = imagecreatetruecolor($count * $this->size + 60, $this->header_height); + $transparentIndex = imagecolorallocate($image, 217, 216, 209); + imagefill($image, 0, 0, $transparentIndex); + $branches = 0; + foreach($header as $head) { + $head = explode(":", $head, 2); + $color = $this->get_color($head[0], true); + $name = $head[1]; + $branches++; + $color = imagecolorallocatealpha($image, $color[0], $color[1], $color[2], 0); + imagettftext($image, 8, 28, ($head[0]-1) * $this->size + 10, $this->header_height-2, $color, realpath(dirname(__FILE__)."/../")."/res/arial.ttf", $name); + } + if(!$branches) die(); + imagecolortransparent($image, $transparentIndex); + header('Content-Type: image/png'); + imagepng($image); + imagedestroy($image); + } + private function parse_data($data) { - //$data = array(); - if(!preg_match("/^([0-9]+)([abc]{1})([0-9]+)\(([^\)]*)\)([a-z0-9,\|]*)(\(([^\)]*)\)|)/i", $data, $matches)) + if(GitConfig::GITGRAPH_BASE64) + $data = base64_decode($data); + if(!preg_match("/^([0-9]+)([abc]{1})([0-9]+)\(([^\)]*)\)([a-z0-9,\|]*)(\(([^\)]*)\)|)/i", $data, $matches)) { + if(preg_match("/head:(.*)/i", $data, $matches)) { + $this->display_header(substr($data, strlen("head:"))); + } return null; + } $data = array(); $data['dot'] = array(); @@ -359,28 +431,28 @@ class graph_image_generator { private function apply_data($data) { foreach($data['l'] as $l) - $this->overlay_image("img/line.png", ($l-1) * $this->size, $this->get_color($l)); + $this->overlay_image("res/line.png", ($l-1) * $this->size, $this->get_color($l)); foreach($data['m'] as $m) { if($m['dd'] == 'r') - $this->overlay_image("img/dot_merge_right.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($m['pos'])); + $this->overlay_image("res/dot_merge_right.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($m['pos'])); else if($m['dd'] == 'l') - $this->overlay_image("img/dot_merge_left.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($m['pos'])); + $this->overlay_image("res/dot_merge_left.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($m['pos'])); if($m['md'] == 'r') - $this->overlay_image("img/".(($m['ml'] & 1) ? "branch" : "merge")."_right.png", ($m['pos'] - 1) * $this->size, $this->get_color($m['pos'])); + $this->overlay_image("res/".(($m['ml'] & 1) ? "branch" : "merge")."_right.png", ($m['pos'] - 1) * $this->size, $this->get_color($m['pos'])); else if($m['md'] == 'l') - $this->overlay_image("img/".(($m['ml'] & 1) ? "branch" : "merge")."_left.png", ($m['pos'] - 1) * $this->size, $this->get_color($m['pos'])); + $this->overlay_image("res/".(($m['ml'] & 1) ? "branch" : "merge")."_left.png", ($m['pos'] - 1) * $this->size, $this->get_color($m['pos'])); if($m['ml'] == 0) - $this->overlay_image("img/line.png", ($m['pos'] - 1) * $this->size, $this->get_color($m['pos'])); + $this->overlay_image("res/line.png", ($m['pos'] - 1) * $this->size, $this->get_color($m['pos'])); foreach($m['hl'] as $hl) { - $this->overlay_image("img/line_h.png", ($hl - 1) * $this->size, $this->get_color($m['pos'])); + $this->overlay_image("res/line_h.png", ($hl - 1) * $this->size, $this->get_color($m['pos'])); } } if($data['dot']['type'] == 'a') - $this->overlay_image("img/dot.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($data['dot']['pos'])); + $this->overlay_image("res/dot.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($data['dot']['pos'])); else if($data['dot']['type'] == 'b') - $this->overlay_image("img/dot_merge.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($data['dot']['pos'])); + $this->overlay_image("res/dot_merge.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($data['dot']['pos'])); else if($data['dot']['type'] == 'c') - $this->overlay_image("img/dot_init.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($data['dot']['pos'])); + $this->overlay_image("res/dot_init.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($data['dot']['pos'])); } diff --git a/htdocs/pages/shortlog.class.php b/htdocs/pages/shortlog.class.php index a7293c8..34cfa80 100644 --- a/htdocs/pages/shortlog.class.php +++ b/htdocs/pages/shortlog.class.php @@ -21,29 +21,46 @@ require_once('lib/graph.class.php'); class shortlog { private $project; private $graph_data; + private $first_commit; public function generate_shortlog($project, $head, $max, $skip, $file = null, $pages = true, $next_page = 0) { $this->project = $project; $content = new ContentProvider('shortlog', 'shortlog'); - $commits = GitCommand::get_commits($project['path'], $head, $max+$skip+1, 0, $file); - $this->graph_data = new graph_data_generator(); - if($head == null) { - //add all refs to the graph - foreach($this->project['refs'] as $ref => $rhash) { - if(preg_match('#^refs/heads/#i', $ref) && preg_match('/^[a-f0-9]*$/i', $rhash)) { - $this->graph_data->add_branch($rhash, $ref); + if(GitConfig::GITGRAPH_ENABLE) { + if($max+$skip >= 2000) { //only load the last 2k commits + $real_skip = ($max+$skip) - 2000; + $skip -= $real_skip; + } else + $real_skip = 0; + } else { + $real_skip = $skip; + $skip = 0; + } + + $commits = GitCommand::get_commits($project['path'], $head, $max+$skip+1, $real_skip, $file); + + if(GitConfig::GITGRAPH_ENABLE) { + $this->graph_data = new graph_data_generator(); + if($head == null) { + //add all refs to the graph + foreach($this->project['refs'] as $ref => $rhash) { + if(preg_match('#^refs/heads/#i', $ref) && preg_match('/^[a-f0-9]*$/i', $rhash)) { + $this->graph_data->add_branch($rhash, $ref); + } } - } - foreach($this->project['refs'] as $ref => $rhash) { - if(preg_match('#^refs/remotes/#i', $ref) && preg_match('/^[a-f0-9]*$/i', $rhash)) { - $this->graph_data->add_branch($rhash, $ref); + foreach($this->project['refs'] as $ref => $rhash) { + if(preg_match('#^refs/remotes/#i', $ref) && preg_match('/^[a-f0-9]*$/i', $rhash)) { + $this->graph_data->add_branch($rhash, $ref); + } } } + $this->graph_data->parse($commits); + $content->set('graph_data', $this->graph_data->get_header_graph()); } - $this->graph_data->parse($commits); $commit_counter = 0; + $this->first_commit = $commits[0]; foreach($commits as $commit) { $commit_counter++; if($commit_counter < $skip) @@ -60,6 +77,10 @@ class shortlog { return $content; } + public function get_first_commit() { + return $this->first_commit; + } + private function shortlog_entry($class, $commit) { $entry = new ContentProvider('shortlog', 'shortlog_entry'); $entry->set('class', $class); @@ -77,7 +98,8 @@ class shortlog { $entry->set('date', $date_str); $entry->set('age', $age_str); } - $entry->set('graph_data', $this->graph_data->get_graph($commit['id'])); + if(GitConfig::GITGRAPH_ENABLE) + $entry->set('graph_data', $this->graph_data->get_graph($commit['id'])); $entry->set('refs', $this->shortlog_commit_refs($commit['id'])); @@ -118,6 +140,8 @@ class page_shortlog { if(!$this->project) return; $project['refs'] = $phpgitweb->get_project_loader()->getProjectRefs($project); + $phpgitweb->append_header_nav("shortlog", null, true); + $this->page = new ContentProvider('shortlog', 'main'); //pages diff --git a/htdocs/pages/summary.class.php b/htdocs/pages/summary.class.php index 30838e1..360ae01 100644 --- a/htdocs/pages/summary.class.php +++ b/htdocs/pages/summary.class.php @@ -26,14 +26,30 @@ class page_summary { if(!$project) return; $project['refs'] = $phpgitweb->get_project_loader()->getProjectRefs($project); + $phpgitweb->append_header_nav("summary", null, true); $this->page = new ContentProvider('summary', 'main'); $this->page->set('description', htmlentities($project['description'])); $this->page->set('owner', htmlentities($project['owner'])); + $giturls = GitConfig::$GIT_BASE_URL; + $urlfield = ""; + foreach($giturls as $url) { + if($urlfield != "") + $urlfield .= "
"; + $urlfield .= $url.(substr($url, -1) == '/' ? '' : '/').$project['name']; + } + if($urlfield != "") + $this->page->set('giturl', new ContentProvider('summary', 'giturl', array('git_link' => $urlfield))); + else + $this->page->set('giturl', ''); + $shortlog = new shortlog(); $this->page->set('shortlog', $shortlog->generate_shortlog($project, null, 16, 0, null, false)); + $first_commit = $shortlog->get_first_commit(); + + $this->page->set('last_change', date('r', $first_commit['committer_time'])); return $this->page; } diff --git a/htdocs/res/.htaccess b/htdocs/res/.htaccess new file mode 100644 index 0000000..43c4479 --- /dev/null +++ b/htdocs/res/.htaccess @@ -0,0 +1,2 @@ +order deny, allow +deny from all \ No newline at end of file diff --git a/htdocs/res/arial.ttf b/htdocs/res/arial.ttf new file mode 100644 index 0000000..abc899c Binary files /dev/null and b/htdocs/res/arial.ttf differ diff --git a/htdocs/res/branch_left.png b/htdocs/res/branch_left.png new file mode 100644 index 0000000..06016a1 Binary files /dev/null and b/htdocs/res/branch_left.png differ diff --git a/htdocs/res/branch_right.png b/htdocs/res/branch_right.png new file mode 100644 index 0000000..1db9a66 Binary files /dev/null and b/htdocs/res/branch_right.png differ diff --git a/htdocs/res/dot.png b/htdocs/res/dot.png new file mode 100644 index 0000000..433e75a Binary files /dev/null and b/htdocs/res/dot.png differ diff --git a/htdocs/res/dot_init.png b/htdocs/res/dot_init.png new file mode 100644 index 0000000..5fbde45 Binary files /dev/null and b/htdocs/res/dot_init.png differ diff --git a/htdocs/res/dot_merge.png b/htdocs/res/dot_merge.png new file mode 100644 index 0000000..70691d0 Binary files /dev/null and b/htdocs/res/dot_merge.png differ diff --git a/htdocs/res/dot_merge_left.png b/htdocs/res/dot_merge_left.png new file mode 100644 index 0000000..0fa7c87 Binary files /dev/null and b/htdocs/res/dot_merge_left.png differ diff --git a/htdocs/res/dot_merge_right.png b/htdocs/res/dot_merge_right.png new file mode 100644 index 0000000..8ccef25 Binary files /dev/null and b/htdocs/res/dot_merge_right.png differ diff --git a/htdocs/res/line.png b/htdocs/res/line.png new file mode 100644 index 0000000..1358887 Binary files /dev/null and b/htdocs/res/line.png differ diff --git a/htdocs/res/line_h.png b/htdocs/res/line_h.png new file mode 100644 index 0000000..0585711 Binary files /dev/null and b/htdocs/res/line_h.png differ diff --git a/htdocs/res/merge_left.png b/htdocs/res/merge_left.png new file mode 100644 index 0000000..cfb950d Binary files /dev/null and b/htdocs/res/merge_left.png differ diff --git a/htdocs/res/merge_right.png b/htdocs/res/merge_right.png new file mode 100644 index 0000000..67e9d32 Binary files /dev/null and b/htdocs/res/merge_right.png differ diff --git a/htdocs/templates/default/summary.tpl b/htdocs/templates/default/summary.tpl index 6ed8a24..c1ee6c1 100644 --- a/htdocs/templates/default/summary.tpl +++ b/htdocs/templates/default/summary.tpl @@ -4,7 +4,7 @@ description%description% owner%owner% last change%last_change% - URL%git_link% + %giturl%
shortlog @@ -17,6 +17,9 @@ %heads% +# [giturl] +URL%git_link% + # [head] %age%