From: Michael Wallner Date: Fri, 6 Mar 2015 08:11:02 +0000 (+0100) Subject: Implement packager and installer hooks X-Git-Tag: v1.1.0~9 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=e1c1b76f0a87c7573e30468763d47c0b97b11e8e;hp=0813c3a5e5dc60c691f7f658b8fe3b51925c6bc1;p=pharext%2Fpharext Implement packager and installer hooks ==Packager hook If not --pecl nor --git are explicitely given, look for a pharext_install.php in --source. This script will be exectuted by the Packager. It must return a callable with the following signature: function(Packager $pkg, $path) : function(Packager $pkg, $path); So, the callback should return another callable. The primary callback is meant to set things like --name and --release, so you don't have to on the command line; build automation FTW. The secondary callback is meant to create the file iterator of the source dir, but if you're in a git clone, you might easily just return a new pharext\GitSourceDir and be done. ==Installer hook The packager will look for a pharext_install.php file within the root of the source dir. This script will be executed by the Installer; it must return a callable with the following signature: function(Installer $installer) : function(Installer $installer); So, again, the callback should return another callable. The primary callback is meant to add your own command line arguments to the CliArgs parser, and the secnodary callback is meant to proccess those args. For --pecl source dirs a pharext_install.php script is automatically generated from the package.xml. ==Examples for pecl_http pharext_package.php ---8<--- getArgs(); $args->name = "pecl_http"; $args->release = current(preg_filter("/^.*PHP_PECL_HTTP_VERSION\s+\"(.*)\".*$/s", "\$1", file("../http.git/php_http.h"))); return function (Packager $packager, $path) { return new GitSourceDir($packager, $path); }; }; ?> --->8--- pharext_install.php ---8<--- getArgs()->compile([ [null, "with-http-zlib-dir", "Where to find zlib", CliArgs::OPTARG], [null, "with-http-libcurl-dir", "Where to find libcurl", CliArgs::OPTARG], [null, "with-http-libevent-dir", "Where to find libev{,ent{,2}}", CliArgs::OPTARG], [null, "with-http-libidn-dir", "Where to find libidn", CliArgs::OPTARG], ]); return function(Installer $installer) { $opts = [ "with-http-zlib-dir", "with-http-libcurl-dir", "with-http-libevent-dir", "with-http-libidn-dir", ]; $args = $installer->getArgs(); foreach ($opts as $opt) { if (isset($args[$opt])) { $args->configure = "--$opt=".$args[$opt]; } } }; }; ?> --->8--- --- diff --git a/Makefile b/Makefile index 6b3dc1f..1027186 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,6 @@ all: bin/pharext bin/pharext: src/* src/pharext/* @echo "Linting changed source files ... " @for file in $?; do php -l $$file | sed -ne '/^No syntax errors/!p' && exit $${PIPESTATUS[0]}; done - @echo "Running tests ... " - @phpunit tests @echo "Creating bin/pharext ... " php -d phar.readonly=0 build/create-phar.php chmod +x $@ diff --git a/bin/pharext b/bin/pharext index e79c042..641f4f5 100755 Binary files a/bin/pharext and b/bin/pharext differ diff --git a/src/pharext/CliArgs.php b/src/pharext/CliArgs.php index 1f07e44..d753931 100644 --- a/src/pharext/CliArgs.php +++ b/src/pharext/CliArgs.php @@ -51,7 +51,7 @@ class CliArgs implements \ArrayAccess * Original option spec * @var array */ - private $orig; + private $orig = []; /** * Compiled spec @@ -79,10 +79,11 @@ class CliArgs implements \ArrayAccess * @return pharext\CliArgs self */ public function compile(array $spec = null) { - $this->orig = $spec; - $this->spec = []; + $this->orig = array_merge($this->orig, $spec); foreach ((array) $spec as $arg) { - $this->spec["-".$arg[0]] = $arg; + if (isset($arg[0])) { + $this->spec["-".$arg[0]] = $arg; + } $this->spec["--".$arg[1]] = $arg; } return $this; @@ -296,12 +297,18 @@ class CliArgs implements \ArrayAccess return $this->offsetGet($o); } function offsetSet($o, $v) { + $osn = $this->optShortName($o); + $oln = $this->optLongName($o); if ($this->optIsMulti($o)) { - $this->args["-".$this->optShortName($o)][] = $v; - $this->args["--".$this->optLongName($o)][] = $v; + if (isset($osn)) { + $this->args["-$osn"][] = $v; + } + $this->args["--$oln"][] = $v; } else { - $this->args["-".$this->optShortName($o)] = $v; - $this->args["--".$this->optLongName($o)] = $v; + if (isset($osn)) { + $this->args["-$osn"] = $v; + } + $this->args["--$oln"] = $v; } } function __set($o, $v) { diff --git a/src/pharext/CliCommand.php b/src/pharext/CliCommand.php index 1299a0e..f4f29b6 100644 --- a/src/pharext/CliCommand.php +++ b/src/pharext/CliCommand.php @@ -16,7 +16,7 @@ trait CliCommand * Output pharext vX.Y.Z header */ function header() { - printf("pharext v%s (c) Michael Wallner \n", VERSION); + printf("pharext v%s (c) Michael Wallner \n\n", VERSION); } /** @@ -24,7 +24,7 @@ trait CliCommand * @param string $prog */ public function help($prog) { - printf("\nUsage:\n\n \$ %s", $prog); + printf("Usage:\n\n \$ %s", $prog); $flags = []; $required = []; @@ -51,9 +51,27 @@ trait CliCommand printf(" [-%s ]", implode("|-", array_column($optional, 0))); } printf("\n\n"); - foreach ($this->args->getSpec() as $spec) { - printf(" -%s|--%s %s", $spec[0], $spec[1], ($spec[3] & CliArgs::REQARG) ? " " : (($spec[3] & CliArgs::OPTARG) ? "[]" : " ")); - printf("%s%s%s", str_repeat(" ", 16-strlen($spec[1])), $spec[2], ($spec[3] & CliArgs::REQUIRED) ? " (REQUIRED)" : ""); + $spc = $this->args->getSpec(); + $max = max(array_map("strlen", array_column($spc, 1))); + $max += $max % 8 + 2; + foreach ($spc as $spec) { + if (isset($spec[0])) { + printf(" -%s|", $spec[0]); + } else { + printf(" "); + } + printf("--%s ", $spec[1]); + if ($spec[3] & CliArgs::REQARG) { + printf(" "); + } elseif ($spec[3] & CliArgs::OPTARG) { + printf("[]"); + } else { + printf(" "); + } + printf("%s%s", str_repeat(" ", $max-strlen($spec[1])+3*!isset($spec[0])), $spec[2]); + if ($spec[3] & CliArgs::REQUIRED) { + printf(" (REQUIRED)"); + } if (isset($spec[4])) { printf(" [%s]", $spec[4]); } diff --git a/src/pharext/Installer.php b/src/pharext/Installer.php index f6c7807..626cfa6 100644 --- a/src/pharext/Installer.php +++ b/src/pharext/Installer.php @@ -40,6 +40,13 @@ class Installer implements Command * @see \pharext\Command::run() */ public function run($argc, array $argv) { + if (($hook = stream_resolve_include_path("pharext_install.php"))) { + $callable = include $hook; + if (is_callable($callable)) { + $recv = $callable($this); + } + } + $errs = []; $prog = array_shift($argv); foreach ($this->args->parse(--$argc, $argv) as $error) { @@ -69,6 +76,10 @@ class Installer implements Command exit(1); } + if (isset($recv)) { + $recv($this); + } + $this->installPackage(); } diff --git a/src/pharext/Packager.php b/src/pharext/Packager.php index b6b05e1..5401b4c 100644 --- a/src/pharext/Packager.php +++ b/src/pharext/Packager.php @@ -70,6 +70,8 @@ class Packager implements Command $this->source = new PeclSourceDir($this, $this->args["source"]); } elseif ($this->args["git"]) { $this->source = new GitSourceDir($this, $this->args["source"]); + } elseif (realpath($this->args["source"]."/pharext_package.php")) { + $this->source = new PharextSourceDir($this, $this->args["source"]); } else { $this->source = new FilteredSourceDir($this, $this->args["source"]); } diff --git a/src/pharext/PeclSourceDir.php b/src/pharext/PeclSourceDir.php index ab71746..ca065ad 100644 --- a/src/pharext/PeclSourceDir.php +++ b/src/pharext/PeclSourceDir.php @@ -25,6 +25,12 @@ class PeclSourceDir implements \IteratorAggregate, SourceDir */ private $path; + /** + * Installer hook + * @var string + */ + private $hook; + /** * @inheritdoc * @see \pharext\SourceDir::__construct() @@ -48,6 +54,18 @@ class PeclSourceDir implements \IteratorAggregate, SourceDir } } + if (($configure = $sxe->xpath("/pecl:package/pecl:extsrcrelease/pecl:configureoption"))) { + $this->hook = tmpfile(); + ob_start(function($s) { + fwrite($this->hook, $s); + return null; + }); + call_user_func(function() use ($configure) { + include __DIR__."/../pharext_install.tpl.php"; + }); + ob_end_flush(); + } + $this->cmd = $cmd; $this->sxe = $sxe; $this->path = $path; @@ -79,6 +97,10 @@ class PeclSourceDir implements \IteratorAggregate, SourceDir * @return Generator */ private function generateFiles() { + if ($this->hook) { + rewind($this->hook); + yield "pharext_install.php" => $this->hook; + } foreach ($this->sxe->xpath("//pecl:file") as $file) { $path = $this->path ."/". $this->dirOf($file) ."/". $file["name"]; if ($this->cmd->getArgs()->verbose) { diff --git a/src/pharext/PharextSourceDir.php b/src/pharext/PharextSourceDir.php new file mode 100644 index 0000000..e0d9a2a --- /dev/null +++ b/src/pharext/PharextSourceDir.php @@ -0,0 +1,32 @@ +cmd = $cmd; + $this->path = $path; + + $callable = include "$path/pharext_package.php"; + if (!is_callable($callable)) { + throw new \Exception("Package hook did not return a callable"); + } + $this->iter = $callable($cmd, $path); + } + + public function getBaseDir() { + return $this->path; + } + + public function getIterator() { + if (!is_callable($this->iter)) { + throw new \Exception("Package hook callback did not return a callable"); + } + return call_user_func($this->iter, $this->cmd, $this->path); + } +} \ No newline at end of file diff --git a/src/pharext_install.tpl.php b/src/pharext_install.tpl.php new file mode 100644 index 0000000..9bf8271 --- /dev/null +++ b/src/pharext_install.tpl.php @@ -0,0 +1,36 @@ + + +/** + * Generated by pharext v at . + */ +namespace pharext; + +return function(Installer $installer) { + $args = $installer->getArgs(); + + + $args->compile([[ + null, + "", + "", + CliArgs::OPTARG, + + "" + + NULL + + + ]]); + + + return function(Installer $installer) { + $args = $installer->getArgs(); + + + if (isset($args[""])) { + $args->configure = "--=".$args[""]; + } + + + }; +}; diff --git a/tests/src/pharext/CliCommandTest.php b/tests/src/pharext/CliCommandTest.php index a2bf3d9..7fd2448 100644 --- a/tests/src/pharext/CliCommandTest.php +++ b/tests/src/pharext/CliCommandTest.php @@ -35,7 +35,6 @@ class CliCommandTest extends \PHPUnit_Framework_TestCase public function testHelp() { $this->expectOutputString(<<]