Fix #5661 - MTrack - daily email large and no branch
[web.mtrack] / MTrack / SCM / Git / CommitHookBridge.php
1 <?php
2
3 require_once 'MTrack/Interface/CommitHookBridge.php';
4 require_once 'MTrack/Repo.php';
5
6 // needs to be run from git-recieve (and it has to be the only thing run.
7
8 class MTrack_SCM_Git_CommitHookBridge extends  IMTrackCommitHookBridge 
9 {
10     
11     var $repo;
12     var $branch = "";
13     var $files = array();
14     var $log = array();
15     var $commits = array();
16     var $fileActions = array(); // file=> delete / modify etc..
17     var $props = array(); // date etc..
18     
19     /**
20     * fills up repo, files, log, commits by running log on the STDIN
21     */
22     
23     function __construct($repo) 
24     {
25         $this->repo = $repo->impl();
26         while (($line = fgets(STDIN)) !== false) {
27             echo "got: $line\n";
28             list($old, $new, $ref) = explode(' ', trim($line), 3);
29             $this->branch = $ref;
30             $this->commits[] = $new;
31   
32             if (preg_match('/^0+$/',$old)) {
33                 continue; // it's a new branch - ignore..
34             }
35   
36             $fp = $this->repo->git(
37                 'log', '--no-color', '--name-status',
38                 '--date=rfc',  "$old..$new"); //$ref, used to be in here??  - but it breaks stuff...
39                 
40                 
41             $props = array();
42             $line = fgets($fp);
43             if (!preg_match("/^commit\s+(\S+)$/", $line)) {
44                 throw new Exception("unexpected output from git log: $line");
45             }
46             $this->props = array();
47             // read key: value properties like Author: / Date: 
48             while (($line = fgets($fp)) !== false) {
49                 $line = rtrim($line);
50                 if (!strlen($line)) break;
51                 if (preg_match("/^(\S+):\s*(.*)\s*$/", $line, $M)) {
52                     $this->props[$M[1]] = $M[2];
53                 }
54             }
55             // read the commit log.
56             while (($line = fgets($fp)) !== false) {
57                 $line = rtrim($line);
58                 if (strncmp($line, '    ', 4)) {
59                     break;
60                 }
61                 $this->log[] = substr($line, 4);
62             }
63             
64             
65             do {
66                 if (preg_match("/^(.+)\s+(\S+)\s*$/", $line, $M)) {
67                     $st = $M[1];
68                     $file = $M[2];
69                     $this->files[$file] = $new;
70                     $this->fileActions[$file] = $st;
71                 }
72               
73             } while (($line = fgets($fp)) !== false);
74         }
75         //print_r($this);exit;
76     }
77
78
79     function enumChangedOrModifiedFileNames()
80     {
81         $ret = array();
82         foreach($this->files as $f=>$com) {
83             if ($this->fileActions[$f] == 'D') {
84                 continue;
85             }
86             $ret[] = $f;
87         }
88         return $ret;
89     }
90
91     function getCommitMessage()
92     {
93         $log = join("\n", $this->log);
94         $log = preg_replace('/\[([a-fA-F0-9]+)\]/',
95           "[changeset:" . $this->repo->getBrowseRootName() . ",\$1]", $log);
96         return $log;
97     }
98
99     function getFileStream($path)
100     {
101         $rev = $this->files[$path];
102
103         // There may be a better way...
104         // ls-tree to determine the hash of the file from this change:
105         $fp = $this->repo->git( 'ls-tree', '-r', $rev, $path);
106         $line = fgets($fp);
107         $fp = null;
108         list($mode, $type, $hash, $name) = preg_split("/\s+/", $line);
109         // now we can cat that blob
110         return $this->repo->git( 'cat-file', 'blob', $hash);
111     }
112
113     function getChangesetDescriptor()
114     {
115         $cs = array();
116         foreach ($this->commits as $ref) {
117           $cs[] = '[changeset:' . $this->repo->getBrowseRootName() . ",$ref]";
118         }
119         return join(", ", $cs);
120     }
121 }