diff options
author | Andreas Gohr <andi@splitbrain.org> | 2014-03-19 11:52:22 +0100 |
---|---|---|
committer | Andreas Gohr <andi@splitbrain.org> | 2014-03-19 18:23:18 +0100 |
commit | 9fb664942d6f51d48d02b592980455259907d9a5 (patch) | |
tree | 507ec8c22ba529fca150dc68c84f8d1f3a3bd235 | |
parent | 496e3a6f34d97e44e44340c1fbd2d3cbc262c05c (diff) | |
download | rpg-9fb664942d6f51d48d02b592980455259907d9a5.tar.gz rpg-9fb664942d6f51d48d02b592980455259907d9a5.tar.bz2 |
converted git tool to new CLI base
-rwxr-xr-x | bin/gittool.php | 231 | ||||
-rw-r--r-- | inc/cli.php | 125 |
2 files changed, 181 insertions, 175 deletions
diff --git a/bin/gittool.php b/bin/gittool.php index f9f68ac94..b429c8d1a 100755 --- a/bin/gittool.php +++ b/bin/gittool.php @@ -3,78 +3,108 @@ if('cli' != php_sapi_name()) die(); ini_set('memory_limit', '128M'); -if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__).'/../').'/'); +if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/'); define('NOSESSION', 1); -require_once(DOKU_INC.'inc/init.php'); +require_once(DOKU_INC . 'inc/init.php'); -$GitToolCLI = new GitToolCLI(); -array_shift($argv); -$command = array_shift($argv); - -switch($command) { - case '': - case 'help': - $GitToolCLI->cmd_help(); - break; - case 'clone': - $GitToolCLI->cmd_clone($argv); - break; - case 'install': - $GitToolCLI->cmd_install($argv); - break; - case 'repo': - case 'repos': - $GitToolCLI->cmd_repos(); - break; - default: - $GitToolCLI->cmd_git($command, $argv); -} /** * Easily manage DokuWiki git repositories * * @author Andreas Gohr <andi@splitbrain.org> */ -class GitToolCLI { - private $color = true; - - public function cmd_help() { - echo <<<EOF -Usage: gittool.php <command> [parameters] - -Manage git repositories for DokuWiki and its plugins and templates. - -EXAMPLE +class GitToolCLI extends DokuCLI { -$> ./bin/gittool.php clone gallery template:ach -$> ./bin/gittool.php repos -$> ./bin/gittool.php origin -v - -COMMANDS + /** + * Register options and arguments on the given $options object + * + * @param DokuCLI_Options $options + * @return void + */ + protected function setup(DokuCLI_Options $options) { + $options->setHelp( + "Manage git repositories for DokuWiki and its plugins and templates.\n\n" . + "EXAMPLE\n\n" . + "$> ./bin/gittool.php clone gallery template:ach\n" . + "$> ./bin/gittool.php repos\n" . + "$> ./bin/gittool.php origin -v\n" + ); -help - This help screen + $options->registerArgument( + 'command', + 'Command to execute. See below', + true + ); -clone <extensions> - Tries to install a known plugin or template (prefix with template:) via - git. Uses the DokuWiki.org plugin repository to find the proper git - repository. Multiple extensions can be given as parameters + $options->registerCommand( + 'clone', + 'Tries to install a known plugin or template (prefix with template:) via git. Uses the DokuWiki.org ' . + 'plugin repository to find the proper git repository. Multiple extensions can be given as parameters' + ); + $options->registerArgument( + 'extension', + 'name of the extension to install, prefix with \'template:\' for templates', + true, + 'clone' + ); -install <extensions> - The same as clone, but when no git source repository can be found, the - extension is installed via download + $options->registerCommand( + 'install', + 'The same as clone, but when no git source repository can be found, the extension is installed via ' . + 'download' + ); + $options->registerArgument( + 'extension', + 'name of the extension to install, prefix with \'template:\' for templates', + true, + 'install' + ); -repos - Lists all git repositories found in this DokuWiki installation + $options->registerCommand( + 'repos', + 'Lists all git repositories found in this DokuWiki installation' + ); -<any> - Any unknown commands are assumed to be arguments to git and will be - executed in all repositories found within this DokuWiki installation + $options->registerCommand( + '*', + 'Any unknown commands are assumed to be arguments to git and will be executed in all repositories ' . + 'found within this DokuWiki installation' + ); + } -EOF; + /** + * Your main program + * + * Arguments and options have been parsed when this is run + * + * @param DokuCLI_Options $options + * @return void + */ + protected function main(DokuCLI_Options $options) { + $command = $options->getCmd(); + if(!$command) $command = array_shift($options->args); + + switch($command) { + case '': + echo $options->help('foo'); + break; + case 'clone': + $this->cmd_clone($options->args); + break; + case 'install': + $this->cmd_install($options->args); + break; + case 'repo': + case 'repos': + $this->cmd_repos(); + break; + default: + $this->cmd_git($command, $options->args); + } } + /** * Tries to install the given extensions using git clone * @@ -88,7 +118,7 @@ EOF; $repo = $this->getSourceRepo($ext); if(!$repo) { - $this->msg_error("could not find a repository for $ext"); + $this->error("could not find a repository for $ext"); $errors[] = $ext; } else { if($this->cloneExtension($ext, $repo)) { @@ -100,8 +130,8 @@ EOF; } echo "\n"; - if($succeeded) $this->msg_success('successfully cloned the following extensions: '.join(', ', $succeeded)); - if($errors) $this->msg_error('failed to clone the following extensions: '.join(', ', $errors)); + if($succeeded) $this->success('successfully cloned the following extensions: ' . join(', ', $succeeded)); + if($errors) $this->error('failed to clone the following extensions: ' . join(', ', $errors)); } /** @@ -117,7 +147,7 @@ EOF; $repo = $this->getSourceRepo($ext); if(!$repo) { - $this->msg_info("could not find a repository for $ext"); + $this->info("could not find a repository for $ext"); if($this->downloadExtension($ext)) { $succeeded[] = $ext; } else { @@ -133,8 +163,8 @@ EOF; } echo "\n"; - if($succeeded) $this->msg_success('successfully installed the following extensions: '.join(', ', $succeeded)); - if($errors) $this->msg_error('failed to install the following extensions: '.join(', ', $errors)); + if($succeeded) $this->success('successfully installed the following extensions: ' . join(', ', $succeeded)); + if($errors) $this->error('failed to install the following extensions: ' . join(', ', $errors)); } /** @@ -152,19 +182,19 @@ EOF; foreach($repos as $repo) { if(!@chdir($repo)) { - $this->msg_error("Could not change into $repo"); + $this->error("Could not change into $repo"); continue; } echo "\n"; - $this->msg_info("executing $shell in $repo"); + $this->info("executing $shell in $repo"); $ret = 0; system($shell, $ret); if($ret == 0) { - $this->msg_success("git succeeded in $repo"); + $this->success("git succeeded in $repo"); } else { - $this->msg_error("git failed in $repo"); + $this->error("git failed in $repo"); } } } @@ -193,23 +223,23 @@ EOF; $url = $plugin->getDownloadURL(); if(!$url) { - $this->msg_error("no download URL for $ext"); + $this->error("no download URL for $ext"); return false; } $ok = false; try { - $this->msg_info("installing $ext via download from $url"); + $this->info("installing $ext via download from $url"); $ok = $plugin->installFromURL($url); } catch(Exception $e) { - $this->msg_error($e->getMessage()); + $this->error($e->getMessage()); } if($ok) { - $this->msg_success("installed $ext via download"); + $this->success("installed $ext via download"); return true; } else { - $this->msg_success("failed to install $ext via download"); + $this->success("failed to install $ext via download"); return false; } } @@ -223,19 +253,19 @@ EOF; */ private function cloneExtension($ext, $repo) { if(substr($ext, 0, 9) == 'template:') { - $target = fullpath(tpl_incdir().'../'.substr($ext, 9)); + $target = fullpath(tpl_incdir() . '../' . substr($ext, 9)); } else { - $target = DOKU_PLUGIN.$ext; + $target = DOKU_PLUGIN . $ext; } - $this->msg_info("cloning $ext from $repo to $target"); + $this->info("cloning $ext from $repo to $target"); $ret = 0; system("git clone $repo $target", $ret); if($ret === 0) { - $this->msg_success("cloning of $ext succeeded"); + $this->success("cloning of $ext succeeded"); return true; } else { - $this->msg_error("cloning of $ext failed"); + $this->error("cloning of $ext failed"); return false; } } @@ -248,17 +278,17 @@ EOF; * @return array */ private function findRepos() { - $this->msg_info('Looking for .git directories'); + $this->info('Looking for .git directories'); $data = array_merge( - glob(DOKU_INC.'.git', GLOB_ONLYDIR), - glob(DOKU_PLUGIN.'*/.git', GLOB_ONLYDIR), - glob(fullpath(tpl_incdir().'../').'/*/.git', GLOB_ONLYDIR) + glob(DOKU_INC . '.git', GLOB_ONLYDIR), + glob(DOKU_PLUGIN . '*/.git', GLOB_ONLYDIR), + glob(fullpath(tpl_incdir() . '../') . '/*/.git', GLOB_ONLYDIR) ); if(!$data) { - $this->msg_error('Found no .git directories'); + $this->error('Found no .git directories'); } else { - $this->msg_success('Found '.count($data).' .git directories'); + $this->success('Found ' . count($data) . ' .git directories'); } $data = array_map('fullpath', array_map('dirname', $data)); return $data; @@ -283,7 +313,7 @@ EOF; if(preg_match('/github\.com\/([^\/]+)\/([^\/]+)/i', $repourl, $m)) { $user = $m[1]; $repo = $m[2]; - return 'https://github.com/'.$user.'/'.$repo.'.git'; + return 'https://github.com/' . $user . '/' . $repo . '.git'; } // match gitorious repos @@ -292,49 +322,20 @@ EOF; $repo = $m[2]; if(!$repo) $repo = $user; - return 'https://git.gitorious.org/'.$user.'/'.$repo.'.git'; + return 'https://git.gitorious.org/' . $user . '/' . $repo . '.git'; } // match bitbucket repos - most people seem to use mercurial there though if(preg_match('/bitbucket\.org\/([^\/]+)\/([^\/]+)/i', $repourl, $m)) { $user = $m[1]; $repo = $m[2]; - return 'https://bitbucket.org/'.$user.'/'.$repo.'.git'; + return 'https://bitbucket.org/' . $user . '/' . $repo . '.git'; } return false; } +} - /** - * Print an error message - * - * @param $string - */ - private function msg_error($string) { - if($this->color) echo "\033[31m"; // red - echo "E: $string\n"; - if($this->color) echo "\033[37m"; // reset - } - /** - * Print a success message - * - * @param $string - */ - private function msg_success($string) { - if($this->color) echo "\033[32m"; // green - echo "S: $string\n"; - if($this->color) echo "\033[37m"; // reset - } - - /** - * Print an info message - * - * @param $string - */ - private function msg_info($string) { - if($this->color) echo "\033[36m"; // cyan - echo "I: $string\n"; - if($this->color) echo "\033[37m"; // reset - } -}
\ No newline at end of file +$GitToolCLI = new GitToolCLI(); +$GitToolCLI->run();
\ No newline at end of file diff --git a/inc/cli.php b/inc/cli.php index 2827ae233..2cba828f0 100644 --- a/inc/cli.php +++ b/inc/cli.php @@ -10,8 +10,6 @@ abstract class DokuCLI { /** @var string the executed script itself */ protected $bin; - /** @var array list of non-option arguments */ - protected $args; /** @var DokuCLI_Options the option parser */ protected $options; /** @var DokuCLI_Colors */ @@ -25,8 +23,6 @@ abstract class DokuCLI { public function __construct() { set_exception_handler(array($this, 'fatal')); - $this->args = $this->readPHPArgv(); - $this->bin = basename(array_shift($this->args)); $this->options = new DokuCLI_Options(); $this->colors = new DokuCLI_Colors(); @@ -46,10 +42,9 @@ abstract class DokuCLI { * Arguments and options have been parsed when this is run * * @param DokuCLI_Options $options - * @param array $args * @return void */ - abstract protected function main(DokuCLI_Options $options, &$args); + abstract protected function main(DokuCLI_Options $options); /** * Execute the CLI program @@ -73,22 +68,24 @@ abstract class DokuCLI { ); // parse - $this->options->parseOptions($this->args); + $this->options->parseOptions(); // handle defaults if($this->options->getOpt('no-colors')) { $this->colors->disable(); } if($this->options->getOpt('help')) { - $this->options->help($this->bin); + echo $this->options->help($this->bin); exit(0); } // check arguments - $this->options->checkArguments($this->args); + $this->options->checkArguments(); // execute - $this->main($this->options, $this->args); + $this->main($this->options); + + exit(0); } /** @@ -98,7 +95,7 @@ abstract class DokuCLI { */ public function fatal($error) { $code = 0; - if(is_a($error, 'Exception')) { + if(is_object($error) && is_a($error, 'Exception')) { /** @var Exception $error */ $code = $error->getCode(); $error = $error->getMessage(); @@ -136,29 +133,6 @@ abstract class DokuCLI { $this->colors->ptln("I: $string", 'cyan'); } - /** - * Safely read the $argv PHP array across different PHP configurations. - * Will take care on register_globals and register_argc_argv ini directives - * - * @throws DokuCLI_Exception - * @return array the $argv PHP array or PEAR error if not registered - */ - private function readPHPArgv() { - global $argv; - if(!is_array($argv)) { - if(!@is_array($_SERVER['argv'])) { - if(!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) { - throw new DokuCLI_Exception( - "Could not read cmd args (register_argc_argv=Off?)", - DOKU_CLI_OPTS_ARG_READ - ); - } - return $GLOBALS['HTTP_SERVER_VARS']['argv']; - } - return $_SERVER['argv']; - } - return $argv; - } } /** @@ -264,14 +238,21 @@ class DokuCLI_Colors { * @author Andreas Gohr <andi@splitbrain.org> */ class DokuCLI_Options { - /** @var array $setup keeps the list of options to parse */ + /** @var array keeps the list of options to parse */ protected $setup; - /** @var array $options store parsed options */ - protected $options; + /** @var array store parsed options */ + protected $options = array(); + /** @var string current parsed command if any */ protected $command = ''; + /** @var array passed non-option arguments*/ + public $args = array(); + + /** @var string the executed script */ + protected $bin; + public function __construct() { $this->setup = array( '' => array( @@ -281,6 +262,9 @@ class DokuCLI_Options { ) ); // default command + $this->args = $this->readPHPArgv(); + $this->bin = basename(array_shift($this->args)); + $this->options = array(); } @@ -317,7 +301,7 @@ class DokuCLI_Options { /** * This registers a sub command * - * Sub commands have their own options and use their own function (not main()) + * Sub commands have their own options and use their own function (not main()). * * @param string $command * @param string $help @@ -365,15 +349,14 @@ class DokuCLI_Options { * * Throws an exception if arguments are missing. Called from parseOptions() * - * @param array $args * @throws DokuCLI_Exception */ - public function checkArguments($args) { - $argc = count($args); + public function checkArguments() { + $argc = count($this->args); $req = 0; foreach($this->setup[$this->command]['args'] as $arg) { - if(!$args['required']) break; // last required arguments seen + if(!$arg['required']) break; // last required arguments seen $req++; } @@ -389,32 +372,31 @@ class DokuCLI_Options { * * Note that command options will overwrite any global options with the same name * - * @param array $args * @throws DokuCLI_Exception */ - public function parseOptions(&$args) { + public function parseOptions() { $non_opts = array(); - $argc = count($args); + $argc = count($this->args); for($i = 0; $i < $argc; $i++) { - $arg = $args[$i]; + $arg = $this->args[$i]; // The special element '--' means explicit end of options. Treat the rest of the arguments as non-options // and end the loop. if($arg == '--') { - $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); + $non_opts = array_merge($non_opts, array_slice($this->args, $i + 1)); break; } // '-' is stdin - a normal argument if($arg == '-') { - $non_opts = array_merge($non_opts, array_slice($args, $i)); + $non_opts = array_merge($non_opts, array_slice($this->args, $i)); break; } // first non-option if($arg{0} != '-') { - $non_opts = array_merge($non_opts, array_slice($args, $i)); + $non_opts = array_merge($non_opts, array_slice($this->args, $i)); break; } @@ -428,8 +410,8 @@ class DokuCLI_Options { // argument required? if($this->setup[$this->command]['opts'][$opt]['needsarg']) { - if(is_null($val) && $i + 1 < $argc && !preg_match('/^--?[\w]/', $args[$i + 1])) { - $val = $args[++$i]; + if(is_null($val) && $i + 1 < $argc && !preg_match('/^--?[\w]/', $this->args[$i + 1])) { + $val = $this->args[++$i]; } if(is_null($val)) { throw new DokuCLI_Exception("Option $arg requires an argument", DokuCLI_Exception::E_OPT_ARG_REQUIRED); @@ -453,8 +435,8 @@ class DokuCLI_Options { // argument required? if($this->setup[$this->command]['opts'][$opt]['needsarg']) { $val = null; - if($i + 1 < $argc && !preg_match('/^--?[\w]/', $args[$i + 1])) { - $val = $args[++$i]; + if($i + 1 < $argc && !preg_match('/^--?[\w]/', $this->args[$i + 1])) { + $val = $this->args[++$i]; } if(is_null($val)) { throw new DokuCLI_Exception("Option $arg requires an argument", DokuCLI_Exception::E_OPT_ARG_REQUIRED); @@ -466,13 +448,13 @@ class DokuCLI_Options { } // parsing is now done, update args array - $args = $non_opts; + $this->args = $non_opts; // if not done yet, check if first argument is a command and reexecute argument parsing if it is - if(!$this->command && $args && isset($this->setup[$args[0]])) { + if(!$this->command && $this->args && isset($this->setup[$this->args[0]]) ) { // it is a command! - $this->command = array_shift($args); - $this->parseOptions($args); // second pass + $this->command = array_shift($this->args); + $this->parseOptions(); // second pass } } @@ -504,10 +486,9 @@ class DokuCLI_Options { /** * Builds a help screen from the available options. You may want to call it from -h or on error * - * @param string $bin name of the script itself * @return string */ - public function help($bin) { + public function help() { $text = ''; $hascommands = (count($this->setup) > 1); @@ -516,7 +497,7 @@ class DokuCLI_Options { $hasargs = (bool) $this->setup[$command]['args']; if(!$command) { - $text .= 'USAGE: ' . $bin; + $text .= 'USAGE: ' . $this->bin; } else { $text .= "\n$command"; } @@ -565,6 +546,30 @@ class DokuCLI_Options { return $text; } + /** + * Safely read the $argv PHP array across different PHP configurations. + * Will take care on register_globals and register_argc_argv ini directives + * + * @throws DokuCLI_Exception + * @return array the $argv PHP array or PEAR error if not registered + */ + private function readPHPArgv() { + global $argv; + if(!is_array($argv)) { + if(!@is_array($_SERVER['argv'])) { + if(!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) { + throw new DokuCLI_Exception( + "Could not read cmd args (register_argc_argv=Off?)", + DOKU_CLI_OPTS_ARG_READ + ); + } + return $GLOBALS['HTTP_SERVER_VARS']['argv']; + } + return $_SERVER['argv']; + } + return $argv; + } + } /** |