2 <?php # vim:ts=2:sw=2:et:ft=php:
3 /* For licensing and copyright terms, see the file named LICENSE */
5 // git-commit-hook what [mtrackconfig]
6 // the cwd is the repo path
7 // a list of "oldrev newrev refname" lines is presented to us on stdin
10 if (isset($argv[2])) {
11 putenv("MTRACK_CONFIG_FILE=" . $argv[2]);
13 include dirname(__FILE__) . '/../inc/common.php';
14 if (file_exists(MTrackConfig::get('core', 'vardir') . '/.initializing')) {
18 ini_set('display_errors', true);
19 $GIT = MTrackConfig::get('tools', 'git');
21 class GitCommitHookBridge implements IMTrackCommitHookBridge {
25 var $commits = array();
27 function __construct($repo) {
32 while (($line = fgets(STDIN)) !== false) {
33 list($old, $new, $ref) = explode(' ', trim($line), 3);
34 $this->commits[] = $new;
36 $fp = run($GIT, 'log', '--no-color', '--name-status',
37 '--date=rfc', $ref, "$old..$new");
40 if (!preg_match("/^commit\s+(\S+)$/", $line)) {
41 throw new Exception("unexpected output from git log: $line");
43 while (($line = fgets($fp)) !== false) {
45 if (!strlen($line)) break;
46 if (preg_match("/^(\S+):\s*(.*)\s*$/", $line, $M)) {
47 $props[$M[1]] = $M[2];
50 while (($line = fgets($fp)) !== false) {
52 if (strncmp($line, ' ', 4)) {
55 $this->log[] = substr($line, 4);
58 if (preg_match("/^(.+)\s+(\S+)\s*$/", $line, $M)) {
61 $this->files[$file] = $new;
63 } while (($line = fgets($fp)) !== false);
66 function enumChangedOrModifiedFileNames() {
67 return array_keys($this->files);
70 function getCommitMessage() {
71 $log = join("\n", $this->log);
72 $log = preg_replace('/\[([a-fA-F0-9]+)\]/',
73 "[changeset:" . $this->repo->getBrowseRootName() . ",\$1]", $log);
77 function getFileStream($path) {
79 $rev = $this->files[$path];
81 // There may be a better way...
82 // ls-tree to determine the hash of the file from this change:
83 $fp = run($GIT, 'ls-tree', '-r', $rev, $path);
86 list($mode, $type, $hash, $name) = preg_split("/\s+/", $line);
87 // now we can cat that blob
88 return run($GIT, 'cat-file', 'blob', $hash);
91 function getChangesetDescriptor() {
93 foreach ($this->commits as $ref) {
94 $cs[] = '[changeset:' . $this->repo->getBrowseRootName() . ",$ref]";
96 return join(", ", $cs);
101 $repo = MTrackRepo::loadByLocation(getcwd());
102 $bridge = new GitCommitHookBridge($repo);
103 $author = MTrackAuth::whoami();
104 if ($author == 'anonymous') {
105 throw new Exception("cannot determine who you are");
107 $author = mtrack_canon_username($author);
108 MTrackAuth::su($author);
109 $checker = new MTrackCommitChecker($repo);
112 $checker->preCommit($bridge);
115 $checker->postCommit($bridge);
118 } catch (Exception $e) {
119 fwrite(STDERR, "\n" . $e->getMessage() .
121 $e->getTraceAsString() .
122 "\n\n ** Commit failed [$action]\n");
129 $args = func_get_args();
131 foreach ($args as $a) {
133 foreach ($a as $arg) {
143 foreach ($all_args as $i => $arg) {
147 $cmd .= escapeshellarg($arg);
151 return popen($cmd, 'r');