continued :)
authorpk910 <philipp@zoelle1.de>
Fri, 15 Feb 2013 01:43:25 +0000 (02:43 +0100)
committerpk910 <philipp@zoelle1.de>
Fri, 15 Feb 2013 01:43:25 +0000 (02:43 +0100)
15 files changed:
htdocs/lib/CommitLoader.class.php [new file with mode: 0644]
htdocs/lib/ContentProvider.class.php
htdocs/lib/GitCommand.class.php
htdocs/lib/PHPGitWeb.class.php
htdocs/lib/ProjectLoader.class.php
htdocs/lib/Tools.class.php
htdocs/lib/Validation.class.php [new file with mode: 0644]
htdocs/pages/commit.class.php [new file with mode: 0644]
htdocs/pages/projects.class.php
htdocs/pages/shortlog.class.php
htdocs/pages/summary.class.php
htdocs/templates/default/commit.tpl [new file with mode: 0644]
htdocs/templates/default/main.tpl
htdocs/templates/default/projects.tpl
htdocs/templates/default/shortlog.tpl

diff --git a/htdocs/lib/CommitLoader.class.php b/htdocs/lib/CommitLoader.class.php
new file mode 100644 (file)
index 0000000..d6e822c
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/* CommitLoader.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/>. 
+ */
+
+class CommitLoader {
+       private $project;
+       
+       public function __construct($project) {
+               $this->project = $project;
+       }
+       
+       public function load($id) {
+               if(!Validation::validate_hash($id)) {
+                       trigger_error("Invalid hash parameter", E_USER_ERROR);
+                       return false;
+               }
+               $commit = GitCommand::get_commit($this->project['path'], $id);
+               return $commit;
+       }
+       
+       
+}
index cd88b91e8b025b8e7347f849bc41f7fa22a8ce25..a32a37fb95d92a2593e5e730ca13b74b2dc4cfe9 100644 (file)
@@ -41,6 +41,8 @@ class ContentProvider {
                        return;
                if(!array_key_exists(strtolower($name), $this->content))
                        $this->content[strtolower($name)] = array();
+               if(!is_array($this->content[strtolower($name)]))
+                       $this->content[strtolower($name)] = array($this->content[strtolower($name)]);
                $this->content[strtolower($name)][] = $value;
        }
        
@@ -76,9 +78,6 @@ class ContentProvider {
                case "year":
                        $rep = date("Y");
                        break;
-               case "title":
-                       $rep = GitConfig::GITWEB_TITLE;
-                       break;
                case "rendertime":
                        $rep = "%rendertime%"; //gets replaced later
                        break;
index 4e20281778e1d6c1ab58642f70a0e4beda3d1c4a..609d0ad7d0575f06a1125b631cf1ce81889580ba 100644 (file)
@@ -20,7 +20,7 @@ class GitCommand {
        private static $git = null;
        private static $counter = 0;
        
-       private static function command_header($git_path = null) {
+       private static function command_header() {
                if(!self::$git) {
                        //find git executable
                        if(GitConfig::GIT_EXEC)
@@ -33,36 +33,41 @@ class GitCommand {
                        }
                }
                $command = self::$git;
-               if($git_path)
-                       $command .= " --git-dir=".$git_path;
+               
                return $command;
        }
        
-       private static function execute($command) {
+       private static function git_execute($params, $git_path = null) {
                $result = array();
+               
+               if($git_path) {
+                       $args = array("--git-dir=".$git_path);
+                       $args = array_merge($args, $params);
+               } else
+                       $args = $params;
+               
+               $command = self::command_header();
+               foreach($args as $arg) {
+                       $command .= ' '.escapeshellarg($arg);
+               }
+               
                exec($command, $result);
                self::$counter++;
                return implode("\n", $result);
        }
        
        public static function core_version() {
-               $command = self::command_header();
-               if(!$command)
-                       return null;
-               $command .= " --version";
-               $version = self::execute($command);
+               $args = array("--version");
+               $version = self::git_execute($args);
                preg_match("/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/i", $version, $result);
                return $result[0];
        }
        
        public static function last_activity($git_path, $ref = null) {
-               $command = self::command_header($git_path);
-               if(!$command)
-                       return null;
-               $command .= " for-each-ref --format=%\(committer\) --sort=-committerdate --count=1";
+               $args = array("for-each-ref", "--format=%(committer)", "--sort=-committerdate", "--count=1");
                if($ref)
-                       $command .= " ".$ref;
-               $age = self::execute($command);
+                       $args[] = $ref;
+               $age = self::git_execute($args, $git_path);
                preg_match("/[0-9]{9,}/i", $age, $result);
                return $result[0];
        }
@@ -71,6 +76,9 @@ class GitCommand {
                $commit = array();
                $rev_lines = explode("\n", str_replace("\r", "", $commit_data));
                $commit['id'] = $rev_lines[0];
+               $commit['parent'] = array();
+               if(!preg_match("/^[a-f0-9]{40}$/i", $commit['id']))
+                       return null;
                foreach($rev_lines as $rev_line) {
                        if(substr($rev_line, 0, 4) == "    ") {
                                if(array_key_exists('text', $commit))
@@ -85,15 +93,17 @@ class GitCommand {
                                else if($opt[0] == "parent")
                                        $commit['parent'][] = $opt[1];
                                else if($opt[0] == "author") {
-                                       preg_match('/(.*) <([^>]*)> ([0-9]*) [+-0-9]*/i', $opt[1], $matches);
+                                       preg_match('/(.*) <([^>]*)> ([0-9]*) ([+\-0-9]{5})/i', $opt[1], $matches);
                                        $commit['author'] = $matches[1];
                                        $commit['author_mail'] = $matches[2];
                                        $commit['author_time'] = $matches[3];
+                                       $commit['author_timezone'] = $matches[4];
                                } else if($opt[0] == "committer") {
-                                       preg_match('/(.*) <([^>]*)> ([0-9]*) [+-0-9]*/i', $opt[1], $matches);
+                                       preg_match('/(.*) <([^>]*)> ([0-9]*) ([+\-0-9]{5})/i', $opt[1], $matches);
                                        $commit['committer'] = $matches[1];
                                        $commit['committer_mail'] = $matches[2];
                                        $commit['committer_time'] = $matches[3];
+                                       $commit['committer_timezone'] = $matches[4];
                                }
                        }
                }
@@ -101,13 +111,10 @@ class GitCommand {
        }
        
        public static function get_commits($git_path, $head, $maxcount, $skip, $file = null) {
-               $command = self::command_header($git_path);
-               if(!$command)
-                       return null;
-               $command .= " rev-list --header --max-count=".$maxcount." --skip=".$skip." ".($head ? $head : "--all")." --";
+               $args = array("rev-list", "--header", "--max-count=".$maxcount, "--skip=".$skip, ($head ? $head : "--all"), "--");
                if($file)
-                       $command .= " ".$file;
-               $commit_list = self::execute($command);
+                       $args[] = $file;
+               $commit_list = self::git_execute($args, $git_path);
                $commits = array();
                foreach(explode("\000", $commit_list) as $commit) {
                        if($commit)
@@ -116,4 +123,19 @@ class GitCommand {
                return $commits;
        }
        
+       public static function get_commit($git_path, $commit_id) {
+               $args = array("rev-list", "--header", "--max-count=1", $commit_id, "--");
+               $commit_data = self::git_execute($args, $git_path);
+               $commit = self::parse_commit($commit_data);
+               return $commit;
+       }
+       
+       public static function get_hash($git_path, $ref) {
+               $args = array("rev-parse", "--verify", "-q", $ref);
+               $result = self::git_execute($args, $git_path);
+               if(prag_match("#([a-f0-9]{40})#i", $result, $match))
+                       return $match[1];
+               return null;
+       }
+       
 }
index 8d16d7ba2b0fdcc80e7ee0b6b8f31217754b1e6d..5789d1f098152191c09d38bd4d2f013fd9451d1f 100644 (file)
 define("PHPGITWEB_VERSION", "0.0.1");
 require_once("lib/ContentProvider.class.php");
 require_once("lib/ProjectLoader.class.php");
+require_once("lib/CommitLoader.class.php");
 require_once("lib/GitCommand.class.php");
 require_once("lib/Tools.class.php");
+require_once("lib/Validation.class.php");
 require_once("lib/graph.class.php");
 
 class PHPGitWeb {
@@ -35,6 +37,7 @@ class PHPGitWeb {
                $this->page->set('git_version', GitCommand::core_version());
                
                $this->project_loader = new ProjectLoader();
+               $this->page->append('title', GitConfig::GITWEB_TITLE);
        }
        
        public function get_project_loader() {
@@ -45,11 +48,12 @@ class PHPGitWeb {
                $this->project = $this->project_loader->getProject($project);
                
                if(!$this->project)
-                       $this->page->append('content', new ContentProvider('main', 'project_error'));
+                       $this->page->append('content', new ContentProvider('main', 'err404_project'));
                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->append_title(" - ".$this->project['name'], false);
                        $this->project_header = new ContentProvider('main', 'project_header');
                        $this->project_header->set('sub_nav', "");
                        $this->page->append('content', $this->project_header);
@@ -91,6 +95,17 @@ class PHPGitWeb {
                        $this->page->append('header_nav', $name);
        }
        
+       public function append_title($name, $prepend_slash = true) {
+               if($prepend_slash)
+                       $this->page->append('title', '/');
+               $this->page->append('title', $name);
+       }
+       
+       public function append_sub_nav($html) {
+               if($this->project_header)
+                       $this->project_header->append('sub_nav', $html);
+       }
+       
        public function load_extension($extension) {
                switch($extension) {
                case "graph":
index a5ebd74f8b40da65015076ef08b3094a195a5c28..20ee218aa6a91a6aecdb301fa59c5bcae76afabc 100644 (file)
@@ -47,6 +47,8 @@ class ProjectLoader {
                $project['name'] = $name;
         
         $dir_seperator = (substr(GitConfig::PROJECT_ROOT, -1) == '/' ? '' : '/');
+               if(!Validation::validate_path($name))
+                       return NULL;
         if(is_dir(GitConfig::PROJECT_ROOT.$dir_seperator.$name))
             $project['path'] = GitConfig::PROJECT_ROOT.$dir_seperator.$name;
         else if(is_dir(GitConfig::PROJECT_ROOT.$dir_seperator.$name.".git"))
index d6f9b640acd129aee8c2e0ad6e79f6be1b9b77f9..d7f9075bff8522dabfc6525cdda50009cea3edae 100644 (file)
@@ -83,6 +83,13 @@ class Tools {
                return $ctext;
        }
        
+       public static function parseTimeZone($timezone) {
+               if(!preg_match("/^([+-])([0-9]{2})([0-9]{2})$/i", $timezone, $treffer))
+                       return 0;
+               $offset = ($treffer[1] == '-' ? -1 : 1) * (($treffer[2] * 3600) + ($treffer[3] * 60));
+               return $offset;
+       }
+       
 }
 
 ?>
\ No newline at end of file
diff --git a/htdocs/lib/Validation.class.php b/htdocs/lib/Validation.class.php
new file mode 100644 (file)
index 0000000..4db14d9
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/* Validation.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/>. 
+ */
+
+class Validation {
+       
+       public static function validate_path($path) {
+               /* Path validation #1
+               * no '.' or '..' as elements of path, i.e. no '.' nor '..'
+               * at the beginning, at the end, and between slashes.
+               * also this catches doubled slashes
+               */
+               if(preg_match('#(^|/)(|\.|\.\.)(/|$)#', $path))
+                       return false;
+               
+               /* Path validation #2
+               * no null characters
+               */
+               if(preg_match('#\0#', $path))
+                       return false;
+               
+               return true;
+       }
+       
+       public static function validate_hash($hash) {
+               /* Hash validation #1
+               * regular hashes [a-f0-9] are always ok
+               */
+               if(preg_match('#^[a-f0-9]{1,40}$#i', $hash))
+                       return true;
+               
+               /* Hash validation #2
+               * must be a valid path
+               */
+               if(!self::validate_path($hash))
+                       return false;
+               
+               /* Hash validation #3
+               * restrictions on ref name according to git-check-ref-format
+               */
+               if(preg_match('#(\.|\.\.|[\000-\040\177 ~^:?*\[\]]|/$)#', $hash))
+                       return false;
+               
+               return true;
+       }
+       
+}
+
+?>
\ No newline at end of file
diff --git a/htdocs/pages/commit.class.php b/htdocs/pages/commit.class.php
new file mode 100644 (file)
index 0000000..17f5678
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+/* commit.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/shortlog.class.php');
+
+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', '<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'], 50, 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'])));
+               }
+               
+               $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 : ""));
+               
+               return $this->page;
+       }
+       
+}
+
+?>
\ No newline at end of file
index ade8eb61b5839a503d5413671a329da19bb18657..be0766b337a7b044c012690c44f501665ab31fab 100644 (file)
@@ -99,7 +99,7 @@ class page_projects {
                
                $age = Tools::age_calculate($project['last_change']);
                
-               $entry->set('ageclass', $age['age_class']);
+               $entry->set('age_class', $age['age_class']);
                $entry->set('age', $age['age_str']);
                return $entry;
        }
index 34cfa8042f35aa6a8108e6c900a979fda062501d..38c8db5e1139a1ff365f3e3fb6f11fa761a19dad 100644 (file)
@@ -22,6 +22,7 @@ class shortlog {
        private $project;
        private $graph_data;
        private $first_commit;
+       private $have_more = false;
        
        public function generate_shortlog($project, $head, $max, $skip, $file = null, $pages = true, $next_page = 0) {
                $this->project = $project;
@@ -66,6 +67,7 @@ class shortlog {
                        if($commit_counter < $skip)
                                continue;
                        if($commit_counter > $max+$skip) {
+                               $this->have_more = true;
                                if($pages) {
                                        $content->append('entries', new ContentProvider('shortlog', 'shortlog_page', array("page" => $next_page)));
                                } else
@@ -81,6 +83,10 @@ class shortlog {
                return $this->first_commit;
        }
        
+       public function get_have_more() {
+               return $this->have_more;
+       }
+       
        private function shortlog_entry($class, $commit) {
                $entry = new ContentProvider('shortlog', 'shortlog_entry');
                $entry->set('class', $class);
@@ -101,17 +107,17 @@ class shortlog {
                if(GitConfig::GITGRAPH_ENABLE)
                        $entry->set('graph_data', $this->graph_data->get_graph($commit['id']));
                
-               $entry->set('refs', $this->shortlog_commit_refs($commit['id']));
+               $entry->set('refs', $this->shortlog_commit_refs($this->project, $commit['id']));
                
                return $entry;
        }
        
-       private function shortlog_commit_refs($hash) {
-               if(!is_array($this->project['refs']))
+       public function shortlog_commit_refs($project, $hash) {
+               if(!is_array($project['refs']))
                        return "";
                $refs = new ContentProvider('shortlog', 'shortlog_refs');
                $found = false;
-               foreach($this->project['refs'] as $ref => $rhash) {
+               foreach($project['refs'] as $ref => $rhash) {
                        if(strtolower($rhash) == strtolower($hash)) {
                                $refexp = explode('/', $ref, 3);
                                $reftype = $refexp[1];
@@ -138,24 +144,45 @@ class page_shortlog {
                $this->phpgitweb = $phpgitweb;
                $this->project = $project;
                if(!$this->project)
-                       return;
+                       return new ContentProvider('main', 'err400');
                $project['refs'] = $phpgitweb->get_project_loader()->getProjectRefs($project);
                $phpgitweb->append_header_nav("shortlog", null, true);
+               $phpgitweb->append_title("shortlog");
                
                $this->page = new ContentProvider('shortlog', 'main');
                
                //pages
                if(array_key_exists('pg', $_GET)) {
+                       $pg = $_GET['pg'];
+                       if($pg < 0)
+                               $pg = 0;
                        $skip = $_GET['pg'] * 100;
                        $next_page = $_GET['pg'] + 1;
                } else {
+                       $pg = 0;
                        $skip = 0;
                        $next_page = 1;
                }
                
+               $subnav = new ContentProvider('shortlog', 'shortlog_subnav');
+               $phpgitweb->append_sub_nav($subnav);
+               
+               if($pg) {
+                       $subnav->set('first', new ContentProvider('shortlog', 'shortlog_subnav_first_link'));
+                       $subnav->set('prev', new ContentProvider('shortlog', 'shortlog_subnav_prev_link', array('page' => ($pg - 1))));
+               } else {
+                       $subnav->set('first', new ContentProvider('shortlog', 'shortlog_subnav_first'));
+                       $subnav->set('prev', new ContentProvider('shortlog', 'shortlog_subnav_prev'));
+               }
+               
                $shortlog = new shortlog();
                $this->page->set('shortlog', $shortlog->generate_shortlog($project, null, 100, $skip, null, true, $next_page));
                
+               if($shortlog->get_have_more())
+                       $subnav->set('next', new ContentProvider('shortlog', 'shortlog_subnav_next_link', array('page' => ($pg + 1))));
+               else
+                       $subnav->set('next', new ContentProvider('shortlog', 'shortlog_subnav_next'));
+               
                return $this->page;
        }
        
index 360ae01b4808fbb7e5af74757c5845afef2f100f..0e3eae63ff62a39c88482c0da6f84f306bfef04a 100644 (file)
@@ -24,9 +24,10 @@ class page_summary {
     public function main($phpgitweb, $project) {
                $this->phpgitweb = $phpgitweb;
                if(!$project)
-                       return;
+                       return new ContentProvider('main', 'err400');
                $project['refs'] = $phpgitweb->get_project_loader()->getProjectRefs($project);
                $phpgitweb->append_header_nav("summary", null, true);
+               $phpgitweb->append_title("summary");
                
                $this->page = new ContentProvider('summary', 'main');
                
@@ -49,7 +50,7 @@ class page_summary {
                $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']));
+               $this->page->set('last_change', gmdate('r', $first_commit['committer_time']));
                
                return $this->page;
        }
diff --git a/htdocs/templates/default/commit.tpl b/htdocs/templates/default/commit.tpl
new file mode 100644 (file)
index 0000000..cb2fc4e
--- /dev/null
@@ -0,0 +1,87 @@
+# [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">&lt;%author_mail%&gt;</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">&lt;%committer_mail%&gt;</a>
+               </td>
+               <td rowspan="2"></td>
+       </tr>
+       <tr>
+               <td></td>
+               <td> %committer_date% (%committer_local_date% %committer_timezone%)</td>
+       </tr>
+       <tr>
+               <td>commit</td>
+               <td class="sha1">%hash%</td>
+       </tr>
+       <tr>
+               <td>tree</td>
+               <td class="sha1"><a class="list" href="?p=%project%&a=tree&h=%tree_hash%&hb=%hash%">%tree_hash%</a></td>
+               <td class="link">
+                       <a href="?p=%project%&a=tree&h=%tree_hash%&hb=%hash%">tree</a> | 
+                       <a title="in format: tar.gz" href="?p=%project%&a=snapshot&h=%hash%&sf=tgz">snapshot</a>
+               </td>
+       </tr>
+%parents%
+</table>
+</div>
+<div class="page_body">
+%full_message%<br/>
+</div>
+
+<div class="list_head">
+</div>
+<table class="diff_tree">
+%tree%
+</table>
+
+
+# [parent]
+       <tr>
+               <td>parent</td>
+               <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>
+               </td>
+       </tr>
+
+# [commit_refs]
+<span class="refs"> %refs%</span>
+
+# [commit_ref_head]
+<span class="head" title="heads/%name%">%name%</span>
+
+# [commit_ref_remote]
+<span class="remote" title="remotes/%name%">%name%</span>
+
+# [commit_ref_tag]
+<span class="tag" title="tags/%name%">%name%</span>
+
+# [tree]
+<tr class="%class%">
+       <td><a class="list" href="?p=%project%&a=blob&h=%hash%&f=%file%">src/mod-helpserv.c</a></td>
+       <td></td>
+       <td class="link">
+               <a href="?p=%project%&a=blobdiff&h=%hash%&f=src/mod-helpserv.c&hp=%parent%">diff</a> | 
+               <a href="?p=%project%&a=blob&h=%hash%&f=%file%">blob</a> | 
+               <a href="?p=%project%&a=history&h=%hash%&f=%file%">history</a></td>
+</tr>
index 52d883df2bcffb756e970a52e0eef163a8b3fee1..d3908a59e682709bc8ddfae82d4c3f5868e00455 100644 (file)
@@ -36,12 +36,27 @@ Rendertime: %rendertime% sec
 </pre>
 </div>
 
-# [project_error]
+# [err400]
 <div class="page_body">
+<br /><br />
+404 - Project needed
+<br /><br />
+</div>
+
+# [err404_project]
+<div class="page_body">
+<br /><br />
 404 - Project not found
 <br /><br />
 </div>
 
+# [err404_object]
+<div class="page_body">
+<br /><br />
+404 - Unknown commit object
+<br /><br />
+</div>
+
 # [project_header]
 <form method="get" enctype="application/x-www-form-urlencoded">
 <div class="search">
index 86911359989772566e9cbda38ac6054b473860b0..f1d37d29a10d2f2c303fea1216a3ae7e804b784f 100644 (file)
@@ -1,4 +1,9 @@
 # [main]
+<form method="get" enctype="application/x-www-form-urlencoded">
+<p class="projsearch">Search:
+<input type="text" name="s"  />
+</p>
+</form>
 <table class="project_list">
        <tr>
                <th>%header_project%</th>
index 6e8ec37759d6c36c71f21a4cde0c1146ac2b91e6..424e9bf8259f1aaf12ae06a58000194d14be4763 100644 (file)
 <span class="remote" title="remotes/%name%"><a href="?p=%project%&a=shortlog&h=%ref_link%">%name%</a></span>
 
 # [shortlog_ref_tag]
-<span class="tag" title="tags/%name%"><a href="?p=%project%&a=shortlog&h=%ref_link%">%name%</a></span>
\ No newline at end of file
+<span class="tag" title="tags/%name%"><a href="?p=%project%&a=shortlog&h=%ref_link%">%name%</a></span>
+
+# [shortlog_subnav]
+%first% &sdot; %prev% &sdot; %next%
+
+# [shortlog_subnav_first_link]
+<a href="?p=%project%&a=shortlog">first</a>
+
+# [shortlog_subnav_first]
+first
+
+# [shortlog_subnav_prev_link]
+<a title="Alt-p" accesskey="p" href="?p=%project%&a=shortlog&pg=%page%">prev</a>
+
+# [shortlog_subnav_prev]
+prev
+
+# [shortlog_subnav_next_link]
+<a title="Alt-n" accesskey="n" href="?p=%project%&a=shortlog&pg=%page%">next</a>
+
+# [shortlog_subnav_next]
+next
+