4e20281778e1d6c1ab58642f70a0e4beda3d1c4a
[phpgitweb.git] / htdocs / lib / GitCommand.class.php
1 <?php
2 /* GitCommand.class.php - phpgitweb
3  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
4  * 
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.
9  * 
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.
14  * 
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/>. 
17  */
18
19 class GitCommand {
20         private static $git = null;
21         private static $counter = 0;
22         
23         private static function command_header($git_path = null) {
24                 if(!self::$git) {
25                         //find git executable
26                         if(GitConfig::GIT_EXEC)
27                                 self::$git = GitConfig::GIT_EXEC;
28                         else
29                                 self::$git = str_replace(array("\n", "\r"), array("", ""), `which git`);
30                         if(!self::$git) {
31                                 trigger_error("Can not find git executable.", E_USER_ERROR);
32                                 self::$git = "git";
33                         }
34                 }
35                 $command = self::$git;
36                 if($git_path)
37                         $command .= " --git-dir=".$git_path;
38                 return $command;
39         }
40         
41         private static function execute($command) {
42                 $result = array();
43                 exec($command, $result);
44                 self::$counter++;
45                 return implode("\n", $result);
46         }
47         
48         public static function core_version() {
49                 $command = self::command_header();
50                 if(!$command)
51                         return null;
52                 $command .= " --version";
53                 $version = self::execute($command);
54                 preg_match("/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/i", $version, $result);
55                 return $result[0];
56         }
57         
58         public static function last_activity($git_path, $ref = null) {
59                 $command = self::command_header($git_path);
60                 if(!$command)
61                         return null;
62                 $command .= " for-each-ref --format=%\(committer\) --sort=-committerdate --count=1";
63                 if($ref)
64                         $command .= " ".$ref;
65                 $age = self::execute($command);
66                 preg_match("/[0-9]{9,}/i", $age, $result);
67                 return $result[0];
68         }
69         
70         private static function parse_commit($commit_data) {
71                 $commit = array();
72                 $rev_lines = explode("\n", str_replace("\r", "", $commit_data));
73                 $commit['id'] = $rev_lines[0];
74                 foreach($rev_lines as $rev_line) {
75                         if(substr($rev_line, 0, 4) == "    ") {
76                                 if(array_key_exists('text', $commit))
77                                         $commit['text'] .= "\n";
78                                 else
79                                         $commit['text'] = '';
80                                 $commit['text'] .= substr($rev_line, 4);
81                         } else {
82                                 $opt = explode(" ", $rev_line, 2);
83                                 if($opt[0] == "tree")
84                                         $commit['tree'] = $opt[1];
85                                 else if($opt[0] == "parent")
86                                         $commit['parent'][] = $opt[1];
87                                 else if($opt[0] == "author") {
88                                         preg_match('/(.*) <([^>]*)> ([0-9]*) [+-0-9]*/i', $opt[1], $matches);
89                                         $commit['author'] = $matches[1];
90                                         $commit['author_mail'] = $matches[2];
91                                         $commit['author_time'] = $matches[3];
92                                 } else if($opt[0] == "committer") {
93                                         preg_match('/(.*) <([^>]*)> ([0-9]*) [+-0-9]*/i', $opt[1], $matches);
94                                         $commit['committer'] = $matches[1];
95                                         $commit['committer_mail'] = $matches[2];
96                                         $commit['committer_time'] = $matches[3];
97                                 }
98                         }
99                 }
100                 return $commit;
101         }
102         
103         public static function get_commits($git_path, $head, $maxcount, $skip, $file = null) {
104                 $command = self::command_header($git_path);
105                 if(!$command)
106                         return null;
107                 $command .= " rev-list --header --max-count=".$maxcount." --skip=".$skip." ".($head ? $head : "--all")." --";
108                 if($file)
109                         $command .= " ".$file;
110                 $commit_list = self::execute($command);
111                 $commits = array();
112                 foreach(explode("\000", $commit_list) as $commit) {
113                         if($commit)
114                                 $commits[] = self::parse_commit($commit);
115                 }
116                 return $commits;
117         }
118         
119 }