use $INPUT to access authentication environment #3750
[dokuwiki.git] / bin / gittool.php
blob5ebd0c5849351c81cc67cbfc5b6e4004d168cb1e
1 #!/usr/bin/env php
2 <?php
4 use splitbrain\phpcli\CLI;
5 use splitbrain\phpcli\Options;
7 if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
8 define('NOSESSION', 1);
9 require_once(DOKU_INC . 'inc/init.php');
11 /**
12 * Easily manage DokuWiki git repositories
14 * @author Andreas Gohr <andi@splitbrain.org>
16 class GitToolCLI extends CLI {
18 /**
19 * Register options and arguments on the given $options object
21 * @param Options $options
22 * @return void
24 protected function setup(Options $options) {
25 $options->setHelp(
26 "Manage git repositories for DokuWiki and its plugins and templates.\n\n" .
27 "$> ./bin/gittool.php clone gallery template:ach\n" .
28 "$> ./bin/gittool.php repos\n" .
29 "$> ./bin/gittool.php origin -v"
32 $options->registerArgument(
33 'command',
34 'Command to execute. See below',
35 true
38 $options->registerCommand(
39 'clone',
40 'Tries to install a known plugin or template (prefix with template:) via git. Uses the DokuWiki.org ' .
41 'plugin repository to find the proper git repository. Multiple extensions can be given as parameters'
43 $options->registerArgument(
44 'extension',
45 'name of the extension to install, prefix with \'template:\' for templates',
46 true,
47 'clone'
50 $options->registerCommand(
51 'install',
52 'The same as clone, but when no git source repository can be found, the extension is installed via ' .
53 'download'
55 $options->registerArgument(
56 'extension',
57 'name of the extension to install, prefix with \'template:\' for templates',
58 true,
59 'install'
62 $options->registerCommand(
63 'repos',
64 'Lists all git repositories found in this DokuWiki installation'
67 $options->registerCommand(
68 '*',
69 'Any unknown commands are assumed to be arguments to git and will be executed in all repositories ' .
70 'found within this DokuWiki installation'
74 /**
75 * Your main program
77 * Arguments and options have been parsed when this is run
79 * @param Options $options
80 * @return void
82 protected function main(Options $options) {
83 $command = $options->getCmd();
84 $args = $options->getArgs();
85 if(!$command) $command = array_shift($args);
87 switch($command) {
88 case '':
89 echo $options->help();
90 break;
91 case 'clone':
92 $this->cmdClone($args);
93 break;
94 case 'install':
95 $this->cmdInstall($args);
96 break;
97 case 'repo':
98 case 'repos':
99 $this->cmdRepos();
100 break;
101 default:
102 $this->cmdGit($command, $args);
107 * Tries to install the given extensions using git clone
109 * @param array $extensions
111 public function cmdClone($extensions) {
112 $errors = array();
113 $succeeded = array();
115 foreach($extensions as $ext) {
116 $repo = $this->getSourceRepo($ext);
118 if(!$repo) {
119 $this->error("could not find a repository for $ext");
120 $errors[] = $ext;
121 } else {
122 if($this->cloneExtension($ext, $repo)) {
123 $succeeded[] = $ext;
124 } else {
125 $errors[] = $ext;
130 echo "\n";
131 if($succeeded) $this->success('successfully cloned the following extensions: ' . join(', ', $succeeded));
132 if($errors) $this->error('failed to clone the following extensions: ' . join(', ', $errors));
136 * Tries to install the given extensions using git clone with fallback to install
138 * @param array $extensions
140 public function cmdInstall($extensions) {
141 $errors = array();
142 $succeeded = array();
144 foreach($extensions as $ext) {
145 $repo = $this->getSourceRepo($ext);
147 if(!$repo) {
148 $this->info("could not find a repository for $ext");
149 if($this->downloadExtension($ext)) {
150 $succeeded[] = $ext;
151 } else {
152 $errors[] = $ext;
154 } else {
155 if($this->cloneExtension($ext, $repo)) {
156 $succeeded[] = $ext;
157 } else {
158 $errors[] = $ext;
163 echo "\n";
164 if($succeeded) $this->success('successfully installed the following extensions: ' . join(', ', $succeeded));
165 if($errors) $this->error('failed to install the following extensions: ' . join(', ', $errors));
169 * Executes the given git command in every repository
171 * @param $cmd
172 * @param $arg
174 public function cmdGit($cmd, $arg) {
175 $repos = $this->findRepos();
177 $shell = array_merge(array('git', $cmd), $arg);
178 $shell = array_map('escapeshellarg', $shell);
179 $shell = join(' ', $shell);
181 foreach($repos as $repo) {
182 if(!@chdir($repo)) {
183 $this->error("Could not change into $repo");
184 continue;
187 $this->info("executing $shell in $repo");
188 $ret = 0;
189 system($shell, $ret);
191 if($ret == 0) {
192 $this->success("git succeeded in $repo");
193 } else {
194 $this->error("git failed in $repo");
200 * Simply lists the repositories
202 public function cmdRepos() {
203 $repos = $this->findRepos();
204 foreach($repos as $repo) {
205 echo "$repo\n";
210 * Install extension from the given download URL
212 * @param string $ext
213 * @return bool|null
215 private function downloadExtension($ext) {
216 /** @var helper_plugin_extension_extension $plugin */
217 $plugin = plugin_load('helper', 'extension_extension');
218 if(!$ext) die("extension plugin not available, can't continue");
220 $plugin->setExtension($ext);
222 $url = $plugin->getDownloadURL();
223 if(!$url) {
224 $this->error("no download URL for $ext");
225 return false;
228 $ok = false;
229 try {
230 $this->info("installing $ext via download from $url");
231 $ok = $plugin->installFromURL($url);
232 } catch(Exception $e) {
233 $this->error($e->getMessage());
236 if($ok) {
237 $this->success("installed $ext via download");
238 return true;
239 } else {
240 $this->success("failed to install $ext via download");
241 return false;
246 * Clones the extension from the given repository
248 * @param string $ext
249 * @param string $repo
250 * @return bool
252 private function cloneExtension($ext, $repo) {
253 if(substr($ext, 0, 9) == 'template:') {
254 $target = fullpath(tpl_incdir() . '../' . substr($ext, 9));
255 } else {
256 $target = DOKU_PLUGIN . $ext;
259 $this->info("cloning $ext from $repo to $target");
260 $ret = 0;
261 system("git clone $repo $target", $ret);
262 if($ret === 0) {
263 $this->success("cloning of $ext succeeded");
264 return true;
265 } else {
266 $this->error("cloning of $ext failed");
267 return false;
272 * Returns all git repositories in this DokuWiki install
274 * Looks in root, template and plugin directories only.
276 * @return array
278 private function findRepos() {
279 $this->info('Looking for .git directories');
280 $data = array_merge(
281 glob(DOKU_INC . '.git', GLOB_ONLYDIR),
282 glob(DOKU_PLUGIN . '*/.git', GLOB_ONLYDIR),
283 glob(fullpath(tpl_incdir() . '../') . '/*/.git', GLOB_ONLYDIR)
286 if(!$data) {
287 $this->error('Found no .git directories');
288 } else {
289 $this->success('Found ' . count($data) . ' .git directories');
291 $data = array_map('fullpath', array_map('dirname', $data));
292 return $data;
296 * Returns the repository for the given extension
298 * @param $extension
299 * @return false|string
301 private function getSourceRepo($extension) {
302 /** @var helper_plugin_extension_extension $ext */
303 $ext = plugin_load('helper', 'extension_extension');
304 if(!$ext) die("extension plugin not available, can't continue");
306 $ext->setExtension($extension);
308 $repourl = $ext->getSourcerepoURL();
309 if(!$repourl) return false;
311 // match github repos
312 if(preg_match('/github\.com\/([^\/]+)\/([^\/]+)/i', $repourl, $m)) {
313 $user = $m[1];
314 $repo = $m[2];
315 return 'https://github.com/' . $user . '/' . $repo . '.git';
318 // match gitorious repos
319 if(preg_match('/gitorious.org\/([^\/]+)\/([^\/]+)?/i', $repourl, $m)) {
320 $user = $m[1];
321 $repo = $m[2];
322 if(!$repo) $repo = $user;
324 return 'https://git.gitorious.org/' . $user . '/' . $repo . '.git';
327 // match bitbucket repos - most people seem to use mercurial there though
328 if(preg_match('/bitbucket\.org\/([^\/]+)\/([^\/]+)/i', $repourl, $m)) {
329 $user = $m[1];
330 $repo = $m[2];
331 return 'https://bitbucket.org/' . $user . '/' . $repo . '.git';
334 return false;
338 // Main
339 $cli = new GitToolCLI();
340 $cli->run();