123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- #!/usr/bin/env php
- <?php
- use splitbrain\phpcli\CLI;
- use splitbrain\phpcli\Options;
- if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
- define('NOSESSION', 1);
- require_once(DOKU_INC . 'inc/init.php');
- /**
- * Easily manage DokuWiki git repositories
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- */
- class GitToolCLI extends CLI {
- /**
- * Register options and arguments on the given $options object
- *
- * @param Options $options
- * @return void
- */
- protected function setup(Options $options) {
- $options->setHelp(
- "Manage git repositories for DokuWiki and its plugins and templates.\n\n" .
- "$> ./bin/gittool.php clone gallery template:ach\n" .
- "$> ./bin/gittool.php repos\n" .
- "$> ./bin/gittool.php origin -v"
- );
- $options->registerArgument(
- 'command',
- 'Command to execute. See below',
- true
- );
- $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'
- );
- $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'
- );
- $options->registerCommand(
- 'repos',
- 'Lists all git repositories found in 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'
- );
- }
- /**
- * Your main program
- *
- * Arguments and options have been parsed when this is run
- *
- * @param Options $options
- * @return void
- */
- protected function main(Options $options) {
- $command = $options->getCmd();
- $args = $options->getArgs();
- if(!$command) $command = array_shift($args);
- switch($command) {
- case '':
- echo $options->help();
- break;
- case 'clone':
- $this->cmdClone($args);
- break;
- case 'install':
- $this->cmdInstall($args);
- break;
- case 'repo':
- case 'repos':
- $this->cmdRepos();
- break;
- default:
- $this->cmdGit($command, $args);
- }
- }
- /**
- * Tries to install the given extensions using git clone
- *
- * @param array $extensions
- */
- public function cmdClone($extensions) {
- $errors = array();
- $succeeded = array();
- foreach($extensions as $ext) {
- $repo = $this->getSourceRepo($ext);
- if(!$repo) {
- $this->error("could not find a repository for $ext");
- $errors[] = $ext;
- } else {
- if($this->cloneExtension($ext, $repo)) {
- $succeeded[] = $ext;
- } else {
- $errors[] = $ext;
- }
- }
- }
- echo "\n";
- if($succeeded) $this->success('successfully cloned the following extensions: ' . join(', ', $succeeded));
- if($errors) $this->error('failed to clone the following extensions: ' . join(', ', $errors));
- }
- /**
- * Tries to install the given extensions using git clone with fallback to install
- *
- * @param array $extensions
- */
- public function cmdInstall($extensions) {
- $errors = array();
- $succeeded = array();
- foreach($extensions as $ext) {
- $repo = $this->getSourceRepo($ext);
- if(!$repo) {
- $this->info("could not find a repository for $ext");
- if($this->downloadExtension($ext)) {
- $succeeded[] = $ext;
- } else {
- $errors[] = $ext;
- }
- } else {
- if($this->cloneExtension($ext, $repo)) {
- $succeeded[] = $ext;
- } else {
- $errors[] = $ext;
- }
- }
- }
- echo "\n";
- if($succeeded) $this->success('successfully installed the following extensions: ' . join(', ', $succeeded));
- if($errors) $this->error('failed to install the following extensions: ' . join(', ', $errors));
- }
- /**
- * Executes the given git command in every repository
- *
- * @param $cmd
- * @param $arg
- */
- public function cmdGit($cmd, $arg) {
- $repos = $this->findRepos();
- $shell = array_merge(array('git', $cmd), $arg);
- $shell = array_map('escapeshellarg', $shell);
- $shell = join(' ', $shell);
- foreach($repos as $repo) {
- if(!@chdir($repo)) {
- $this->error("Could not change into $repo");
- continue;
- }
- $this->info("executing $shell in $repo");
- $ret = 0;
- system($shell, $ret);
- if($ret == 0) {
- $this->success("git succeeded in $repo");
- } else {
- $this->error("git failed in $repo");
- }
- }
- }
- /**
- * Simply lists the repositories
- */
- public function cmdRepos() {
- $repos = $this->findRepos();
- foreach($repos as $repo) {
- echo "$repo\n";
- }
- }
- /**
- * Install extension from the given download URL
- *
- * @param string $ext
- * @return bool|null
- */
- private function downloadExtension($ext) {
- /** @var helper_plugin_extension_extension $plugin */
- $plugin = plugin_load('helper', 'extension_extension');
- if(!$ext) die("extension plugin not available, can't continue");
- $plugin->setExtension($ext);
- $url = $plugin->getDownloadURL();
- if(!$url) {
- $this->error("no download URL for $ext");
- return false;
- }
- $ok = false;
- try {
- $this->info("installing $ext via download from $url");
- $ok = $plugin->installFromURL($url);
- } catch(Exception $e) {
- $this->error($e->getMessage());
- }
- if($ok) {
- $this->success("installed $ext via download");
- return true;
- } else {
- $this->success("failed to install $ext via download");
- return false;
- }
- }
- /**
- * Clones the extension from the given repository
- *
- * @param string $ext
- * @param string $repo
- * @return bool
- */
- private function cloneExtension($ext, $repo) {
- if(substr($ext, 0, 9) == 'template:') {
- $target = fullpath(tpl_incdir() . '../' . substr($ext, 9));
- } else {
- $target = DOKU_PLUGIN . $ext;
- }
- $this->info("cloning $ext from $repo to $target");
- $ret = 0;
- system("git clone $repo $target", $ret);
- if($ret === 0) {
- $this->success("cloning of $ext succeeded");
- return true;
- } else {
- $this->error("cloning of $ext failed");
- return false;
- }
- }
- /**
- * Returns all git repositories in this DokuWiki install
- *
- * Looks in root, template and plugin directories only.
- *
- * @return array
- */
- private function findRepos() {
- $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)
- );
- if(!$data) {
- $this->error('Found no .git directories');
- } else {
- $this->success('Found ' . count($data) . ' .git directories');
- }
- $data = array_map('fullpath', array_map('dirname', $data));
- return $data;
- }
- /**
- * Returns the repository for the given extension
- *
- * @param $extension
- * @return false|string
- */
- private function getSourceRepo($extension) {
- /** @var helper_plugin_extension_extension $ext */
- $ext = plugin_load('helper', 'extension_extension');
- if(!$ext) die("extension plugin not available, can't continue");
- $ext->setExtension($extension);
- $repourl = $ext->getSourcerepoURL();
- if(!$repourl) return false;
- // match github repos
- if(preg_match('/github\.com\/([^\/]+)\/([^\/]+)/i', $repourl, $m)) {
- $user = $m[1];
- $repo = $m[2];
- return 'https://github.com/' . $user . '/' . $repo . '.git';
- }
- // match gitorious repos
- if(preg_match('/gitorious.org\/([^\/]+)\/([^\/]+)?/i', $repourl, $m)) {
- $user = $m[1];
- $repo = $m[2];
- if(!$repo) $repo = $user;
- 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 false;
- }
- }
- // Main
- $cli = new GitToolCLI();
- $cli->run();
|