From 7ccf382e89737f430fb8da72cef752dc2252f324 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Wed, 2 Sep 2015 17:01:37 +0200 Subject: [PATCH] add bin/pharext.update Updates the pharext code within an .ext.phar without the real need of re-packaging. Usage: $ ./bin/pharext.update [-hvq] [--] -h|--help Display this help -v|--verbose More output -q|--quiet Less output --signature Show pharext signature --license Show pharext license --version Show pharext version -- path Path to .ext.phar to update (REQUIRED) (MULTIPLE) --- .gitignore | 2 +- Makefile | 8 +- bin/pharext | Bin 84497 -> 84913 bytes bin/pharext.update | Bin 0 -> 84927 bytes bin/pharext.update.pubkey | 9 ++ build/{create-phar.php => pharext.php} | 0 build/pharext.update.php | 25 +++++ composer.json | 7 +- src/pharext/Installer.php | 24 ++--- src/pharext/Task/PharBuild.php | 7 +- src/pharext/Task/PharStub.php | 51 ++++++++++ src/pharext/Updater.php | 131 +++++++++++++++++++++++++ src/pharext_updater.php | 36 +++++++ 13 files changed, 277 insertions(+), 23 deletions(-) create mode 100755 bin/pharext.update create mode 100644 bin/pharext.update.pubkey rename build/{create-phar.php => pharext.php} (100%) create mode 100644 build/pharext.update.php create mode 100644 src/pharext/Task/PharStub.php create mode 100644 src/pharext/Updater.php create mode 100644 src/pharext_updater.php diff --git a/.gitignore b/.gitignore index a660ac2..e541637 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,6 @@ nbproject/ *.phar *.phar.gz *.phar.bz2 -build/pharext.key +build/*.key *.phar* *.pubkey diff --git a/Makefile b/Makefile index 887b82d..4f0045a 100644 --- a/Makefile +++ b/Makefile @@ -2,13 +2,13 @@ # build bin/pharext # -all: bin/pharext +all: bin/pharext bin/pharext.update -bin/pharext: src/* src/pharext/* src/pharext/*/* src/pharext/*/*/* +bin/%: build/%.php src/* src/pharext/* src/pharext/*/* 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 "Creating bin/pharext ... " - php -d phar.readonly=0 build/create-phar.php + @echo "Creating $@ ... " + php -d phar.readonly=0 $< test: @echo "Running tests ... " diff --git a/bin/pharext b/bin/pharext index b464635584534dc679a2dcced3f27219c49fe2b5..766c44b56dc65f2553d2e97ba1de90aeca1936ab 100755 GIT binary patch delta 5008 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 SY0T0soA93nx;e8J%=#~2MH=A% diff --git a/bin/pharext.update b/bin/pharext.update new file mode 100755 index 0000000000000000000000000000000000000000..a568e9d781175be6edae8e4bc10da408043278f9 GIT binary patch literal 84927 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 Oyz|aG5AQv`_x}N1k53E$ literal 0 HcmV?d00001 diff --git a/bin/pharext.update.pubkey b/bin/pharext.update.pubkey new file mode 100644 index 0000000..7690045 --- /dev/null +++ b/bin/pharext.update.pubkey @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0tzV2ptX5/W1qRb+jMzo +2AMOoih9nHw6Psd53iKVuNidLtriX/ujqJdcoHuQhn+t5AZkiEJm4susZvRGWiub +0VNzhq4k+whsJXOAkdoqWwyxd0KmcL3mWnvb52sVOj+pLn0NkKI7gwJ56pP/lHNA +Zd73LMNUUuw/bT2po4jts4UqVuRr50xU7SVUbQxZ/nbwKi1T62+7gehRBKScskAL +Wuya8KCTRMcskRUiOEQc9FRSxaQL4ULyPO3sYwxRhWtuDDdSjiMZUzIRDjl1SbS2 +n+mipwyi7DBLv15qfXucq5fRmUUKBEEI9ggihCtRiW49A1SJK2Bra4V1PjqZhhyq +6QIDAQAB +-----END PUBLIC KEY----- diff --git a/build/create-phar.php b/build/pharext.php similarity index 100% rename from build/create-phar.php rename to build/pharext.php diff --git a/build/pharext.update.php b/build/pharext.update.php new file mode 100644 index 0000000..d5f8fb9 --- /dev/null +++ b/build/pharext.update.php @@ -0,0 +1,25 @@ + "pharext.update", + "license" => file_get_contents(__DIR__."/../LICENSE") +], false))->run(); + +if (getenv("SIGN")) { + $pass = (new pharext\Task\Askpass)->run(); + $sign = new pharext\Task\PharSign($file, __DIR__."/pharext.update.key", $pass); + $pkey = $sign->run(); + $pkey->exportPublicKey(__DIR__."/../bin/pharext.update.pubkey"); +} + +/* we do not need the extra logic of Task\PharRename */ +rename($file, __DIR__."/../bin/pharext.update"); diff --git a/composer.json b/composer.json index b4aea13..78ca9cc 100644 --- a/composer.json +++ b/composer.json @@ -4,5 +4,10 @@ "keywords": ["ext", "extension", "phar", "package", "install"], "type": "project", "license": "BSD-2-Clause", - "bin": ["bin/pharext", "bin/pharext.pubkey"] + "bin": [ + "bin/pharext", + "bin/pharext.pubkey", + "bin/pharext.update", + "bin/pharext.update.key" + ] } diff --git a/src/pharext/Installer.php b/src/pharext/Installer.php index 0171eae..b5dba6d 100644 --- a/src/pharext/Installer.php +++ b/src/pharext/Installer.php @@ -14,19 +14,19 @@ use SplObjectStorage; class Installer implements Command { use CliCommand; - + /** * Cleanups * @var array */ private $cleanup = []; - + /** * Create the command */ public function __construct() { $this->args = new CliArgs([ - ["h", "help", "Display help", + ["h", "help", "Display help", CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT], ["v", "verbose", "More output", CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG], @@ -35,7 +35,7 @@ class Installer implements Command ["p", "prefix", "PHP installation prefix if phpize is not in \$PATH, e.g. /opt/php7", CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::REQARG], ["n", "common-name", "PHP common program name, e.g. php5 or zts-php", - CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::REQARG, + CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::REQARG, "php"], ["c", "configure", "Additional extension configure flags, e.g. -c --with-flag", CliArgs::OPTIONAL|CliArgs::MULTI|CliArgs::REQARG], @@ -58,7 +58,7 @@ class Installer implements Command CliArgs::OPTIONAL|CliArgs::SINGLE|CliArgs::NOARG|CliArgs::HALT], ]); } - + /** * Perform cleaniup */ @@ -67,13 +67,13 @@ class Installer implements Command $cleanup->run(); } } - + private function extract($phar) { $temp = (new Task\Extract($phar))->run($this->verbosity()); $this->cleanup[] = new Task\Cleanup($temp); return $temp; } - + private function hooks(SplObjectStorage $phars) { $hook = []; foreach ($phars as $phar) { @@ -90,7 +90,7 @@ class Installer implements Command private function load() { $list = new SplObjectStorage(); - $phar = extension_loaded("Phar") + $phar = extension_loaded("Phar") ? new Phar(Phar::running(false)) : new Archive(PHAREXT_PHAR); $temp = $this->extract($phar); @@ -104,7 +104,7 @@ class Installer implements Command $list[$dep_phar] = $this->extract($dep_phar); } } - + /* the actual ext.phar at last */ $list[$phar] = $temp; return $list; @@ -189,7 +189,7 @@ class Installer implements Command exit(self::EINSTALL); } } - + /** * Phpize + trinity */ @@ -199,7 +199,7 @@ class Installer implements Command $phpize->run($this->verbosity()); // configure - $configure = new Task\Configure($temp, $this->args->configure, $this->args->prefix, $this->args{"common-name"}); + $configure = new Task\Configure($temp, $this->args->configure, $this->args->prefix, $this->args->{"common-name"}); $configure->run($this->verbosity()); // make @@ -222,7 +222,7 @@ class Installer implements Command $sudo = isset($this->args->sudo) ? $this->args->sudo : null; $type = $this->metadata("type") ?: "extension"; - + $activate = new Task\Activate($temp, $files, $type, $this->args->prefix, $this->args{"common-name"}, $sudo); if (!$activate->run($this->verbosity())) { $this->info("Extension already activated ...\n"); diff --git a/src/pharext/Task/PharBuild.php b/src/pharext/Task/PharBuild.php index 25dd7a4..d2c06be 100644 --- a/src/pharext/Task/PharBuild.php +++ b/src/pharext/Task/PharBuild.php @@ -65,11 +65,8 @@ class PharBuild implements Task if ($this->meta) { $phar->setMetadata($this->meta); } - if (is_file($this->stub)) { - $stub = preg_replace_callback('/^#include <([^>]+)>/m', function($includes) { - return file_get_contents($includes[1], true, null, 5); - }, file_get_contents($this->stub)); - $phar->setStub($stub); + if ($this->stub) { + (new PharStub($phar, $this->stub))->run($verbose); } $phar->buildFromIterator((new Task\BundleGenerator)->run()); diff --git a/src/pharext/Task/PharStub.php b/src/pharext/Task/PharStub.php new file mode 100644 index 0000000..bbaaf73 --- /dev/null +++ b/src/pharext/Task/PharStub.php @@ -0,0 +1,51 @@ +phar = $phar; + if (!file_exists($this->stub = $stub)) { + throw new Exception("File '$stub' does not exist"); + } + } + + /** + * @param bool $verbose + */ + function run($verbose = false) { + if ($verbose) { + printf("Using stub '%s'...\n", basename($this->stub)); + } + $stub = preg_replace_callback('/^#include <([^>]+)>/m', function($includes) { + return file_get_contents($includes[1], true, null, 5); + }, file_get_contents($this->stub)); + if ($this->phar->isCompressed() && substr($stub, 0, 2) === "#!") { + $stub = substr($stub, strpos($stub, "\n")+1); + } + $this->phar->setStub($stub); + } +} diff --git a/src/pharext/Updater.php b/src/pharext/Updater.php new file mode 100644 index 0000000..bee5ed6 --- /dev/null +++ b/src/pharext/Updater.php @@ -0,0 +1,131 @@ +args = new Cli\Args([ + ["h", "help", "Display this help", + Cli\Args::OPTIONAL|Cli\Args::SINGLE|Cli\Args::NOARG|Cli\Args::HALT], + ["v", "verbose", "More output", + Cli\Args::OPTIONAL|Cli\Args::SINGLE|Cli\Args::NOARG], + ["q", "quiet", "Less output", + Cli\Args::OPTIONAL|Cli\Args::SINGLE|Cli\Args::NOARG], + [null, "signature", "Show pharext signature", + Cli\Args::OPTIONAL|Cli\Args::SINGLE|Cli\Args::NOARG|Cli\Args::HALT], + [null, "license", "Show pharext license", + Cli\Args::OPTIONAL|Cli\Args::SINGLE|Cli\Args::NOARG|Cli\Args::HALT], + [null, "version", "Show pharext version", + Cli\Args::OPTIONAL|Cli\Args::SINGLE|Cli\Args::NOARG|Cli\Args::HALT], + [0, "path", "Path to .ext.phar to update", + Cli\Args::REQUIRED|Cli\Args::MULTI], + ]); + } + + /** + * @inheritdoc + * @see \pharext\Command::run() + */ + public function run($argc, array $argv) { + $errs = []; + $prog = array_shift($argv); + foreach ($this->args->parse(--$argc, $argv) as $error) { + $errs[] = $error; + } + + if ($this->args["help"]) { + $this->header(); + $this->help($prog); + exit; + } + + try { + foreach (["signature", "license", "version"] as $opt) { + if ($this->args[$opt]) { + printf("%s\n", $this->metadata($opt)); + exit; + } + } + } catch (\Exception $e) { + $this->error("%s\n", $e->getMessage()); + exit(self::EARGS); + } + + + foreach ($this->args->validate() as $error) { + $errs[] = $error; + } + + if ($errs) { + if (!$this->args["quiet"]) { + $this->header(); + } + foreach ($errs as $err) { + $this->error("%s\n", $err); + } + printf("\n"); + if (!$this->args["quiet"]) { + $this->help($prog); + } + exit(self::EARGS); + } + + foreach ($this->args[0] as $file) { + if (file_exists($file)) { + $this->updatePackage(new SplFileInfo($file)); + } else { + $this->error("File '%s' does not exist\n", $file); + exit(self::EARGS); + } + } + } + + private function replacePharext($temp) { + $phar = new Phar($temp, Phar::CURRENT_AS_SELF); + $phar->startBuffering(); + + // replace current pharext files + $core = (new Task\BundleGenerator)->run($this->verbosity()); + $phar->buildFromIterator($core); + $stub = __DIR__."/../pharext_installer.php"; + (new Task\PharStub($phar, $stub))->run($this->verbosity()); + + // check dependencies + foreach ($phar as $info) { + if (fnmatch("*.ext.phar*", $info->getBasename())) { + $this->updatePackage($info, $phar); + } + } + + $phar->stopBuffering(); + } + + private function updatePackage(SplFileInfo $file, Phar $phar = null) { + $this->info("Updating pharext core in '%s'...\n", basename($file)); + + $temp = new Tempname("update", substr(strstr($file, ".ext.phar"), 4)); + + if (!copy($file->getPathname(), $temp)) { + throw new Exception; + } + + $this->replacePharext($temp); + + if ($phar) { + $phar->addFile($temp, $file); + } elseif (!rename($temp, $file->getPathname())) { + throw new Exception; + } + } +} diff --git a/src/pharext_updater.php b/src/pharext_updater.php new file mode 100644 index 0000000..94167c2 --- /dev/null +++ b/src/pharext_updater.php @@ -0,0 +1,36 @@ +#!/usr/bin/php -dphar.readonly=0 +run($argc, $argv); + +__HALT_COMPILER(); -- 2.30.2