X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=htdocs%2Flib%2FGitCommand.class.php;h=a8ede915817beaafc0e070ddcb8027248bd8ae2a;hb=38cb4c7eb8706a5e500957185493e2025fde5dc1;hp=4e20281778e1d6c1ab58642f70a0e4beda3d1c4a;hpb=0a6d29345b57ef71b076003e18d13efd3478764c;p=phpgitweb.git diff --git a/htdocs/lib/GitCommand.class.php b/htdocs/lib/GitCommand.class.php index 4e20281..a8ede91 100644 --- a/htdocs/lib/GitCommand.class.php +++ b/htdocs/lib/GitCommand.class.php @@ -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,131 @@ 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(preg_match("#([a-f0-9]{40})#i", $result, $match)) + return $match[1]; + 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) { + 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[] = "-c"; + 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(); + foreach(explode("\n", $result) as $line) { + if($line == "") + continue; + $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); + } }