Open Journal Systems  3.3.0
GuzzleSubSplitTask.php
1 <?php
10 require_once 'phing/tasks/ext/git/GitBaseTask.php';
11 
12 // base - base of tree to split out
13 // subIndicatorFile - composer.json, package.xml?
14 class GuzzleSubSplitTask extends GitBaseTask
15 {
19  protected $remote = null;
20 
24  protected $heads = null;
25 
29  protected $tags = null;
30 
34  protected $base = null;
35 
40  protected $subIndicatorFile = 'composer.json';
41 
45  protected $dryRun = null;
46 
50  protected $noHeads = false;
51 
55  protected $noTags = false;
56 
60  protected $splits;
61 
62  public function setRemote($str)
63  {
64  $this->remote = $str;
65  }
66 
67  public function getRemote()
68  {
69  return $this->remote;
70  }
71 
72  public function setHeads($str)
73  {
74  $this->heads = explode(',', $str);
75  }
76 
77  public function getHeads()
78  {
79  return $this->heads;
80  }
81 
82  public function setTags($str)
83  {
84  $this->tags = explode(',', $str);
85  }
86 
87  public function getTags()
88  {
89  return $this->tags;
90  }
91 
92  public function setBase($str)
93  {
94  $this->base = $str;
95  }
96 
97  public function getBase()
98  {
99  return $this->base;
100  }
101 
102  public function setSubIndicatorFile($str)
103  {
104  $this->subIndicatorFile = $str;
105  }
106 
107  public function getSubIndicatorFile()
108  {
110  }
111 
112  public function setDryRun($bool)
113  {
114  $this->dryRun = (bool) $bool;
115  }
116 
117  public function getDryRun()
118  {
119  return $this->dryRun;
120  }
121 
122  public function setNoHeads($bool)
123  {
124  $this->noHeads = (bool) $bool;
125  }
126 
127  public function getNoHeads()
128  {
129  return $this->noHeads;
130  }
131 
132  public function setNoTags($bool)
133  {
134  $this->noTags = (bool) $bool;
135  }
136 
137  public function getNoTags()
138  {
139  return $this->noTags;
140  }
141 
145  protected $client = null;
146 
150  public function main()
151  {
152  $repo = $this->getRepository();
153  if (empty($repo)) {
154  throw new BuildException('"repository" is a required parameter');
155  }
156 
157  $remote = $this->getRemote();
158  if (empty($remote)) {
159  throw new BuildException('"remote" is a required parameter');
160  }
161 
162  chdir($repo);
163  $this->client = $this->getGitClient(false, $repo);
164 
165  // initalized yet?
166  if (!is_dir('.subsplit')) {
167  $this->subsplitInit();
168  } else {
169  // update
170  $this->subsplitUpdate();
171  }
172 
173  // find all splits based on heads requested
174  $this->findSplits();
175 
176  // check that GitHub has the repos
177  $this->verifyRepos();
178 
179  // execute the subsplits
180  $this->publish();
181  }
182 
183  public function publish()
184  {
185  $this->log('DRY RUN ONLY FOR NOW');
186  $base = $this->getBase();
187  $base = rtrim($base, '/') . '/';
188  $org = $this->getOwningTarget()->getProject()->getProperty('github.org');
189 
190  $splits = array();
191 
192  $heads = $this->getHeads();
193  foreach ($heads as $head) {
194  foreach ($this->splits[$head] as $component => $meta) {
195  $splits[] = $base . $component . ':git@github.com:'. $org.'/'.$meta['repo'];
196  }
197 
198  $cmd = 'git subsplit publish ';
199  $cmd .= escapeshellarg(implode(' ', $splits));
200 
201  if ($this->getNoHeads()) {
202  $cmd .= ' --no-heads';
203  } else {
204  $cmd .= ' --heads='.$head;
205  }
206 
207  if ($this->getNoTags()) {
208  $cmd .= ' --no-tags';
209  } else {
210  if ($this->getTags()) {
211  $cmd .= ' --tags=' . escapeshellarg(implode(' ', $this->getTags()));
212  }
213  }
214 
215  passthru($cmd);
216  }
217  }
218 
222  public function subsplitUpdate()
223  {
224  $repo = $this->getRepository();
225  $this->log('git-subsplit update...');
226  $cmd = $this->client->getCommand('subsplit');
227  $cmd->addArgument('update');
228  try {
229  $cmd->execute();
230  } catch (Exception $e) {
231  throw new BuildException('git subsplit update failed'. $e);
232  }
233  chdir($repo . '/.subsplit');
234  passthru('php ../composer.phar update --dev');
235  chdir($repo);
236  }
237 
241  public function subsplitInit()
242  {
243  $remote = $this->getRemote();
244  $cmd = $this->client->getCommand('subsplit');
245  $this->log('running git-subsplit init ' . $remote);
246 
247  $cmd->setArguments(array(
248  'init',
249  $remote
250  ));
251 
252  try {
253  $output = $cmd->execute();
254  } catch (Exception $e) {
255  throw new BuildException('git subsplit init failed'. $e);
256  }
257  $this->log(trim($output), Project::MSG_INFO);
258  $repo = $this->getRepository();
259  chdir($repo . '/.subsplit');
260  passthru('php ../composer.phar install --dev');
261  chdir($repo);
262  }
263 
269  protected function findSplits()
270  {
271  $this->log("checking heads for subsplits");
272  $repo = $this->getRepository();
273  $base = $this->getBase();
274 
275  $splits = array();
276  $heads = $this->getHeads();
277 
278  if (!empty($base)) {
279  $base = '/' . ltrim($base, '/');
280  } else {
281  $base = '/';
282  }
283 
284  chdir($repo . '/.subsplit');
285  foreach ($heads as $head) {
286  $splits[$head] = array();
287 
288  // check each head requested *BEFORE* the actual subtree split command gets it
289  passthru("git checkout '$head'");
290  $ds = new DirectoryScanner();
291  $ds->setBasedir($repo . '/.subsplit' . $base);
292  $ds->setIncludes(array('**/'.$this->subIndicatorFile));
293  $ds->scan();
294  $files = $ds->getIncludedFiles();
295 
296  // Process the files we found
297  foreach ($files as $file) {
298  $pkg = file_get_contents($repo . '/.subsplit' . $base .'/'. $file);
299  $pkg_json = json_decode($pkg, true);
300  $name = $pkg_json['name'];
301  $component = str_replace('/composer.json', '', $file);
302  // keep this for split cmd
303  $tmpreponame = explode('/', $name);
304  $reponame = $tmpreponame[1];
305  $splits[$head][$component]['repo'] = $reponame;
306  $nscomponent = str_replace('/', '\\', $component);
307  $splits[$head][$component]['desc'] = "[READ ONLY] Subtree split of $nscomponent: " . $pkg_json['description'];
308  }
309  }
310 
311  // go back to how we found it
312  passthru("git checkout master");
313  chdir($repo);
314  $this->splits = $splits;
315  }
316 
322  protected function verifyRepos()
323  {
324  $this->log('verifying GitHub target repos');
325  $github_org = $this->getOwningTarget()->getProject()->getProperty('github.org');
326  $github_creds = $this->getOwningTarget()->getProject()->getProperty('github.basicauth');
327 
328  if ($github_creds == 'username:password') {
329  $this->log('Skipping GitHub repo checks. Update github.basicauth in build.properties to verify repos.', 1);
330  return;
331  }
332 
333  $ch = curl_init('https://api.github.com/orgs/'.$github_org.'/repos?type=all');
334  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
335  curl_setopt($ch, CURLOPT_USERPWD, $github_creds);
336  // change this when we know we can use our bundled CA bundle!
337  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
338  $result = curl_exec($ch);
339  curl_close($ch);
340  $repos = json_decode($result, true);
341  $existing_repos = array();
342 
343  // parse out the repos we found on GitHub
344  foreach ($repos as $repo) {
345  $tmpreponame = explode('/', $repo['full_name']);
346  $reponame = $tmpreponame[1];
347  $existing_repos[$reponame] = $repo['description'];
348  }
349 
350  $heads = $this->getHeads();
351  foreach ($heads as $head) {
352  foreach ($this->splits[$head] as $component => $meta) {
353 
354  $reponame = $meta['repo'];
355 
356  if (!isset($existing_repos[$reponame])) {
357  $this->log("Creating missing repo $reponame");
358  $payload = array(
359  'name' => $reponame,
360  'description' => $meta['desc'],
361  'homepage' => 'http://www.guzzlephp.org/',
362  'private' => true,
363  'has_issues' => false,
364  'has_wiki' => false,
365  'has_downloads' => true,
366  'auto_init' => false
367  );
368  $ch = curl_init('https://api.github.com/orgs/'.$github_org.'/repos');
369  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
370  curl_setopt($ch, CURLOPT_USERPWD, $github_creds);
371  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
372  curl_setopt($ch, CURLOPT_POST, 1);
373  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
374  // change this when we know we can use our bundled CA bundle!
375  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
376  $result = curl_exec($ch);
377  echo "Response code: ".curl_getinfo($ch, CURLINFO_HTTP_CODE)."\n";
378  curl_close($ch);
379  } else {
380  $this->log("Repo $reponame exists", 2);
381  }
382  }
383  }
384  }
385 }
GuzzleSubSplitTask\setRemote
setRemote($str)
Definition: GuzzleSubSplitTask.php:62
GuzzleSubSplitTask\subsplitUpdate
subsplitUpdate()
Definition: GuzzleSubSplitTask.php:222
GuzzleSubSplitTask\getHeads
getHeads()
Definition: GuzzleSubSplitTask.php:77
GuzzleSubSplitTask\getSubIndicatorFile
getSubIndicatorFile()
Definition: GuzzleSubSplitTask.php:107
GuzzleSubSplitTask\getRemote
getRemote()
Definition: GuzzleSubSplitTask.php:67
GuzzleSubSplitTask\setSubIndicatorFile
setSubIndicatorFile($str)
Definition: GuzzleSubSplitTask.php:102
GuzzleSubSplitTask\main
main()
Definition: GuzzleSubSplitTask.php:150
GuzzleSubSplitTask\publish
publish()
Definition: GuzzleSubSplitTask.php:183
GuzzleSubSplitTask\$dryRun
$dryRun
Definition: GuzzleSubSplitTask.php:45
GuzzleSubSplitTask\setDryRun
setDryRun($bool)
Definition: GuzzleSubSplitTask.php:112
GuzzleSubSplitTask\$noTags
$noTags
Definition: GuzzleSubSplitTask.php:55
GuzzleSubSplitTask\getDryRun
getDryRun()
Definition: GuzzleSubSplitTask.php:117
GuzzleSubSplitTask\setTags
setTags($str)
Definition: GuzzleSubSplitTask.php:82
GuzzleSubSplitTask\findSplits
findSplits()
Definition: GuzzleSubSplitTask.php:269
GuzzleSubSplitTask\getTags
getTags()
Definition: GuzzleSubSplitTask.php:87
GuzzleSubSplitTask\$base
$base
Definition: GuzzleSubSplitTask.php:34
GuzzleSubSplitTask\setHeads
setHeads($str)
Definition: GuzzleSubSplitTask.php:72
GuzzleSubSplitTask\$tags
$tags
Definition: GuzzleSubSplitTask.php:29
GuzzleSubSplitTask\$subIndicatorFile
$subIndicatorFile
Definition: GuzzleSubSplitTask.php:40
GuzzleSubSplitTask\getNoHeads
getNoHeads()
Definition: GuzzleSubSplitTask.php:127
GuzzleSubSplitTask\getNoTags
getNoTags()
Definition: GuzzleSubSplitTask.php:137
GuzzleSubSplitTask\getBase
getBase()
Definition: GuzzleSubSplitTask.php:97
GuzzleSubSplitTask\$client
$client
Definition: GuzzleSubSplitTask.php:145
GuzzleSubSplitTask\setNoHeads
setNoHeads($bool)
Definition: GuzzleSubSplitTask.php:122
GuzzleSubSplitTask\setBase
setBase($str)
Definition: GuzzleSubSplitTask.php:92
GuzzleSubSplitTask\verifyRepos
verifyRepos()
Definition: GuzzleSubSplitTask.php:322
GuzzleSubSplitTask\$splits
$splits
Definition: GuzzleSubSplitTask.php:60
GuzzleSubSplitTask\$remote
$remote
Definition: GuzzleSubSplitTask.php:19
GuzzleSubSplitTask\subsplitInit
subsplitInit()
Definition: GuzzleSubSplitTask.php:241
GuzzleSubSplitTask\$heads
$heads
Definition: GuzzleSubSplitTask.php:24
GuzzleSubSplitTask\setNoTags
setNoTags($bool)
Definition: GuzzleSubSplitTask.php:132
GuzzleSubSplitTask
Definition: GuzzleSubSplitTask.php:14
GuzzleSubSplitTask\$noHeads
$noHeads
Definition: GuzzleSubSplitTask.php:50