php warnings
[Pman.MTrack] / Merger.php
1 <?php
2 /**
3  * concept is to merge commits from a live or working tree
4  * into the 'release tree'
5  *
6  *
7  * step 1 = render the log of differences..
8  *
9  *
10  * First run issues:
11  *  -- our doc commit changes loads of files.. and makes the layout pointless.
12  *  -- ?? grouping by day??? // expand/collapse.. 
13  * 
14  *
15  */
16
17 require_once 'Pman.php';
18
19 class Pman_MTrack_Merger extends Pman {
20     
21     var $live = 'master';
22     var $release = 'github';
23     
24     
25     // function getAuth() - from log..
26     function getAuth()
27     {
28         parent::getAuth();
29         $au = $this->getAuthUser();
30         if (!$au || $au->company()->comptype != 'OWNER') {
31             $this->jautherr();
32         }
33         $this->authUser = $au;
34         return true;
35     }
36     
37     
38     function get($pi, $opts= array())
39     {
40         
41         $this->pi = 'default/roojs1'; // fixme..
42         
43         $this->repo = DB_DataObject::factory('mtrack_repos');
44         $this->filename = $this->repo->loadFromPath($this->pi);
45         
46         if (!$this->repo->id) {
47             $this->err("invalid repo");
48         };
49           
50         //if (!$this->projectPerm($this->repo->project_id, 'MTrack.Repos', 'S')) {
51         //    $this->err("no perm for this repo ");
52         //}
53         if (isset($_REQUEST['_tree'])) {
54             $this->tree();
55         }
56         
57         if (isset($_REQUEST['_changedFiles'])) {
58             $this->changedFiles($_REQUEST['_changedFiles']);
59         }
60         if (isset($_REQUEST['_preview'])) {
61             $this->preview($_REQUEST['_preview']);
62         }
63         if (isset($_REQUEST['_merge'])) {
64             $this->merge($_REQUEST['_merge']);
65         }
66         $this->jerr("invalid url");
67         exit;
68         
69     }
70     
71     function post($pi) {
72         return $this->get($pi);
73     }
74     
75     function tree()
76     {
77         
78         $live = 'master';
79         $release = 'github';
80          
81         $this->repo->debug = 1;
82         $ar = $this->repo->history("/", null, "rev",  "{$this->release}..{$this->live}");
83         
84         // the point of this is to extract all the revisions, and group them.
85         
86         
87         
88         //echo '<PRE>';print_R($ar);
89         
90         // need to get a 2 dimensional array of
91         // files along top, and commints down.
92         $cfiles = array();
93         $rows = array();
94         foreach($ar as $commit) {
95             
96             $files = $commit->files;
97             $day = date("Y-m-d", strtotime($commit->ctime));
98             if (!isset($days[$day])) { 
99                 $days[$day] = array(
100                     'text' => $day,
101                     'rev' => $day,
102                     'children' => array()
103                 );
104             }
105             $time= date("H:i:s", strtotime($commit->ctime));
106             if (!isset($days[$day]['children'][$time])) { 
107                 $days[$day]['children'][$time] = array(
108                     'text' => $time,
109                     'rev' => $day . ' ' . $time,
110                     'commits' =>array(),
111                 );
112             }
113             $days[$day]['children'][$time]['children'][] = array(
114                 'text'=> $commit->changelog,
115                 'rev' => $commit->rev,
116                 'leaf' => true
117             );
118         }
119         $out = array();
120         
121         foreach($days as $d=>$do) {
122             $dcn = $do['children'];
123             $do['children'] = array();
124             foreach($dcn as $t=>$to) {
125                 $to['rev']  = $to['children'][0]['rev'];
126                 $do['children'][] = $to;
127             }
128             $do['rev'] = $do['children'][0]['rev'];
129             $out[] = $do;
130         }
131         
132         $this->jdata($out);
133         
134          
135         
136     }
137     
138     
139
140
141
142     function changedFiles($rev)
143     {
144         // list the files that have changed..
145         // in theory you could click a number of them and only merge those changes..
146         // need to do a git diff.. and just get a list of files..
147         
148         $rev = preg_replace('/[^a-z0-9]+/', '',$rev);
149         //$this->repo->impl()->debug = 1;
150         $fh = $this->repo->impl()->git('diff', '--numstat' ,  "{$this->release}..{$rev}", '--', "");
151         // returns ADDED \t REMOVED \t NAME (might include rename/etc. info)
152         $rows = array();
153         
154         while (false !== ($line = fgets($fh))) {
155             //var_Dump($line);
156             $ar = explode("\t", trim($line));
157             $rows[] = array(
158                 'added' => $ar[0],
159                 'removed' => $ar[1],
160                 'filename' => $ar[2],
161             );
162             
163             
164         }
165         fclose($fh);
166         $this->jdata($rows);
167          
168
169     }
170     
171     
172
173     function preview($rev)
174     {
175         // list the files that have changed..
176         // in theory you could click a number of them and only merge those changes..
177         // need to do a git diff.. and just get a list of files..
178         
179         $rev = preg_replace('/[^a-z0-9]+/', '',$rev);
180         //$this->repo->impl()->debug = 1;
181         $files = '';
182         if (!empty($_POST['files'])) {
183             $files = json_decode($_POST['files']);
184         }
185         
186         
187         $fh = $this->repo->impl()->git('diff', "-w", "{$this->release}..{$rev}", '--', $files);
188         echo "<PRE> Commit: " . $rev ."</PRE>";
189         echo '<PRE>' . htmlspecialchars(stream_get_contents($fh)) . '</PRE>';
190         fclose($fh);
191         exit;
192          
193
194     }
195     
196     
197     function merge($rev)
198     {
199         
200         $mi = $this->repo->history("/", 1, "rev", $rev);
201        // echo '<PRE>';print_R($mi);exit;
202         
203
204         
205         
206         $wd = $this->repo->getWorkingCopy();
207         $wd->git('checkout', '-b', $this->release, 'remotes/origin/'. $this->release);
208         
209         
210         
211         $patchfile = $this->tempName('txt');
212         
213         $files = '';
214         if (!empty($_POST['files'])) {
215             
216            
217             // if we select all the files, we should do a merge, rather than a commit..
218             $files = $_POST['files'] == '_all_' ? '_all_' : json_decode($_POST['files']);
219         }
220         
221         
222         if (is_array($files)) { 
223             
224             $fh = $this->repo->impl()->git('diff',   "{$this->release}..{$rev}", '--', $files);
225             $of = fopen($patchfile, 'w');
226             stream_copy_to_stream($fh, $of);
227             fclose($of); fclose($fh);
228             //var_dump($patch);
229             $patch = System::which('patch');
230             chdir($wd->dir);
231             $cmd = "$patch -p1 < " . $patchfile;
232             `$cmd`;  //eg . patch -p1 < /var/lib/php5/MTrackTMPgZFeAN.txt
233         } else { 
234             $wd->git('merge', '--squash' , $rev);
235         }
236           
237         //echo $cmd;
238         
239         $commit = (object) array(
240             'when' =>  $mi[0]->ctime,
241             'reason' => $_REQUEST['message'],
242             'name'  => $this->authUser->name,
243             'email' => $this->authUser->email,
244         );
245         
246         $res = $wd->commit($commit);
247         if (!is_array($files)) {
248             // we do an actually merge commit seperatly from the merge diff, so that
249             // our logs show a nice history in each of those commits.
250             // not sure if this is a good idea or not..
251             $wd->git('merge', '-m', "Merge Commit with working branch (no code changed)" , $rev);
252         }
253         
254         
255         $res .= $wd->push();
256         $this->jok($res);
257         
258        // $wd->checkout($this->release);
259         // generate the patch
260         // apply the patch
261         // commit with message..
262         // push
263         
264         
265         
266         
267         
268         
269         
270         
271         
272     }
273     
274     
275     
276     
277 }