From: Michael Wallner Date: Fri, 27 Mar 2015 19:08:44 +0000 (+0100) Subject: more refactoring; now the package hook starts to make sense X-Git-Tag: v3.0.0~13 X-Git-Url: https://git.m6w6.name/?p=pharext%2Fpharext;a=commitdiff_plain;h=e990b6dabecbdaf98b8d8b2173b0d697f9b2b754 more refactoring; now the package hook starts to make sense --- diff --git a/Makefile b/Makefile index 433b800..4c78e66 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ bin/pharext: src/* src/pharext/* src/pharext/*/* test: @echo "Running tests ... " - @phpunit tests + @php -dphar.readonly=0 `which phpunit` tests clean: rm bin/pharext* diff --git a/bin/pharext b/bin/pharext index 911b258..c32af32 100755 Binary files a/bin/pharext and b/bin/pharext differ diff --git a/src/pharext/Cli/Args.php b/src/pharext/Cli/Args.php index f0b0498..38cfaca 100644 --- a/src/pharext/Cli/Args.php +++ b/src/pharext/Cli/Args.php @@ -67,24 +67,27 @@ class Args implements \ArrayAccess /** * Compile the original spec - * @param array $spec + * @param array|Traversable $spec */ - public function __construct(array $spec = null) { - $this->compile($spec); + public function __construct($spec = null) { + if (is_array($spec) || $spec instanceof Traversable) { + $this->compile($spec); + } + } /** * Compile the original spec - * @param array $spec + * @param array|Traversable $spec * @return pharext\CliArgs self */ - public function compile(array $spec = null) { - $this->orig = array_merge($this->orig, (array) $spec); - foreach ((array) $spec as $arg) { + public function compile($spec) { + foreach ($spec as $arg) { if (isset($arg[0])) { $this->spec["-".$arg[0]] = $arg; } $this->spec["--".$arg[1]] = $arg; + $this->orig[] = $arg; } return $this; } diff --git a/src/pharext/Cli/Command.php b/src/pharext/Cli/Command.php index 0cc0bb4..6ad2c80 100644 --- a/src/pharext/Cli/Command.php +++ b/src/pharext/Cli/Command.php @@ -110,15 +110,13 @@ trait Command * @see \pharext\Command::error() */ public function error($fmt) { - if (!$this->args->quiet) { - if (!isset($fmt)) { - $fmt = "%s\n"; - $arg = error_get_last()["message"]; - } else { - $arg = array_slice(func_get_args(), 1); - } - vfprintf(STDERR, "ERROR: $fmt", $arg); + if (!isset($fmt)) { + $fmt = "%s\n"; + $arg = error_get_last()["message"]; + } else { + $arg = array_slice(func_get_args(), 1); } + vfprintf(STDERR, "ERROR: $fmt", $arg); } /** @@ -183,21 +181,16 @@ trait Command } /** - * rm -r - * @param string $dir + * Verbosity + * @return boolean */ - private function rm($dir) { - foreach (scandir($dir) as $entry) { - if ($entry === "." || $entry === "..") { - continue; - } elseif (is_dir("$dir/$entry")) { - $this->rm("$dir/$entry"); - } elseif (!unlink("$dir/$entry")) { - $this->warn(null); - } - } - if (!rmdir($dir)) { - $this->warn(null); + public function verbosity() { + if ($this->args->verbose) { + return true; + } elseif ($this->args->quiet) { + return false; + } else { + return null; } } } diff --git a/src/pharext/ExecCmd.php b/src/pharext/ExecCmd.php index 84bb708..7e657f3 100644 --- a/src/pharext/ExecCmd.php +++ b/src/pharext/ExecCmd.php @@ -57,16 +57,19 @@ class ExecCmd /** * Execute a program with escalated privileges handling interactive password prompt * @param string $command - * @param string $output - * @param int $status + * @param bool $verbose + * @return int exit status */ - private function suExec($command, &$output, &$status) { + private function suExec($command, $verbose = null) { if (!($proc = proc_open($command, [STDIN,["pipe","w"],["pipe","w"]], $pipes))) { - $status = -1; + $this->status = -1; throw new Exception("Failed to run {$command}"); } + $stdout = $pipes[1]; $passwd = 0; + $checks = 10; + while (!feof($stdout)) { $R = [$stdout]; $W = []; $E = []; if (!stream_select($R, $W, $E, null)) { @@ -74,14 +77,49 @@ class ExecCmd } $data = fread($stdout, 0x1000); /* only check a few times */ - if ($passwd++ < 10) { + if ($passwd < $checks) { + $passwd++; if (stristr($data, "password")) { + $passwd = $checks + 1; printf("\n%s", $data); + continue; + } + } elseif ($passwd > $checks) { + /* new line after pw entry */ + printf("\n"); + $passwd = $checks; + } + + if ($verbose === null) { + print $this->progress($data, 0); + } else { + if ($verbose) { + printf("%s\n", $data); } + $this->output .= $data; } - $output .= $data; } - $status = proc_close($proc); + if ($verbose === null) { + $this->progress("", PHP_OUTPUT_HANDLER_FINAL); + } + return $this->status = proc_close($proc); + } + + /** + * Output handler that displays some progress while soaking output + * @param string $string + * @param int $flags + * @return string + */ + private function progress($string, $flags) { + static $c = 0; + static $s = ["\\","|","/","-"]; + + $this->output .= $string; + + return $flags & PHP_OUTPUT_HANDLER_FINAL + ? " \r" + : sprintf(" %s\r", $s[$c++ % count($s)]); } /** @@ -97,7 +135,7 @@ class ExecCmd } if ($this->sudo) { - $this->suExec(sprintf($this->sudo." 2>&1", $exec), $this->output, $this->status); + $this->suExec(sprintf($this->sudo." 2>&1", $exec), $this->verbose); } elseif ($this->verbose) { ob_start(function($s) { $this->output .= $s; @@ -105,6 +143,10 @@ class ExecCmd }, 1); passthru($exec, $this->status); ob_end_flush(); + } elseif ($this->verbose !== false /* !quiet */) { + ob_start([$this, "progress"], 1); + passthru($exec . " 2>&1", $this->status); + ob_end_flush(); } else { exec($exec ." 2>&1", $output, $this->status); $this->output = implode("\n", $output); diff --git a/src/pharext/Installer.php b/src/pharext/Installer.php index 83a40ad..60ca226 100644 --- a/src/pharext/Installer.php +++ b/src/pharext/Installer.php @@ -55,20 +55,39 @@ class Installer implements Command private function extract(Phar $phar) { $this->debug("Extracting %s ...\n", basename($phar->getPath())); - return (new Task\Extract($phar))->run($this->args->verbose); + return (new Task\Extract($phar))->run($this->verbosity()); } - + private function hooks(SplObjectStorage $phars) { - $hooks = []; + $hook = []; foreach ($phars as $phar) { - if (isset($phar["pharext_install.php"])) { - $callable = include $phar["pharext_install.php"]; - if (is_callable($callable)) { - $hooks[] = $callable($this); + if (isset($phar["pharext_package.php"])) { + $sdir = include $phar["pharext_package.php"]; + if ($sdir instanceof SourceDir) { + $this->args->compile($sdir->getArgs()); + $hook[] = $sdir; } } } - return $hooks; + return $hook; + } + + private function load() { + $list = new SplObjectStorage(); + $phar = new Phar(Phar::running(false)); + $temp = $this->extract($phar); + + foreach ($phar as $entry) { + $dep_file = $entry->getBaseName(); + if (fnmatch("*.ext.phar*", $dep_file)) { + $dep_phar = new Phar("$temp/$dep_file"); + $list[$dep_phar] = $this->extract($dep_phar); + } + } + + /* the actual ext.phar at last */ + $list[$phar] = $temp; + return $list; } /** @@ -77,20 +96,8 @@ class Installer implements Command */ public function run($argc, array $argv) { try { - $list = new SplObjectStorage(); - $phar = new Phar(Phar::running(false)); - $temp = $this->extract($phar); - - foreach ($phar as $entry) { - $dep_file = $entry->getBaseName(); - if (fnmatch("*.ext.phar*", $dep_file)) { - $dep_phar = new Phar("$temp/$dep_file"); - $list[$dep_phar] = $this->extract($dep_phar); - } - } - /* the actual ext.phar at last */ - $list[$phar] = $temp; - + /* load the phar(s) */ + $list = $this->load(); /* installer hooks */ $hook = $this->hooks($list); } catch (\Exception $e) { @@ -141,10 +148,8 @@ class Installer implements Command try { /* post process hooks */ - foreach ($hook as $callback) { - if (is_callable($callback)) { - $callback($this); - } + foreach ($hook as $sdir) { + $sdir->setArgs($this->args); } } catch (\Exception $e) { $this->error("%s\n", $e->getMessage()); @@ -173,31 +178,27 @@ class Installer implements Command // phpize $this->info("Running phpize ...\n"); $phpize = new Task\Phpize($temp, $this->args->prefix, $this->args->{"common-name"}); - $phpize->run($this->args->verbose); + $phpize->run($this->verbosity()); // configure $this->info("Running configure ...\n"); $configure = new Task\Configure($temp, $this->args->configure, $this->args->prefix, $this->args{"common-name"}); - $configure->run($this->args->verbose); + $configure->run($this->verbosity()); // make $this->info("Running make ...\n"); $make = new Task\Make($temp); - $make->run($this->args->verbose); + $make->run($this->verbosity()); // install $this->info("Running make install ...\n"); $sudo = isset($this->args->sudo) ? $this->args->sudo : null; $install = new Task\Make($temp, ["install"], $sudo); - $install->run($this->args->verbose); + $install->run($this->verbosity()); } private function cleanup($temp) { - if (is_dir($temp)) { - $this->rm($temp); - } elseif (file_exists($temp)) { - unlink($temp); - } + (new Task\Cleanup($temp))->run(); } private function activate($temp) { @@ -213,7 +214,7 @@ class Installer implements Command $this->info("Running INI activation ...\n"); $activate = new Task\Activate($temp, $files, $type, $this->args->prefix, $this->args{"common-name"}, $sudo); - if (!$activate->run($this->args->verbose)) { + if (!$activate->run($this->verbosity())) { $this->info("Extension already activated ...\n"); } } diff --git a/src/pharext/Packager.php b/src/pharext/Packager.php index b3be6d0..3cf4f5b 100644 --- a/src/pharext/Packager.php +++ b/src/pharext/Packager.php @@ -5,6 +5,7 @@ namespace pharext; use Phar; use pharext\Cli\Args as CliArgs; use pharext\Cli\Command as CliCommand; +use pharext\Exception; /** * The extension packaging command executed by bin/pharext @@ -71,11 +72,7 @@ class Packager implements Command */ function __destruct() { foreach ($this->cleanup as $cleanup) { - if (is_dir($cleanup)) { - $this->rm($cleanup); - } elseif (file_exists($cleanup)) { - unlink($cleanup); - } + $cleanup->run(); } } @@ -112,16 +109,7 @@ class Packager implements Command * so e.g. name and version can be overriden and CliArgs * does not complain about missing arguments */ - if ($this->args["source"]) { - $source = $this->localize($this->args["source"]); - if ($this->args["pecl"]) { - $this->source = new SourceDir\Pecl($this, $source); - } elseif ($this->args["git"]) { - $this->source = new SourceDir\Git($this, $source); - } else { - $this->source = new SourceDir\Pharext($this, $source); - } - } + $this->loadSource(); } catch (\Exception $e) { $errs[] = $e->getMessage(); } @@ -159,17 +147,17 @@ class Packager implements Command $task = new Task\GitClone($source); } else { $task = new Task\StreamFetch($source, function($bytes_pct) { - $this->debug(" %3d%% [%s>%s] \r", + $this->info(" %3d%% [%s>%s] \r%s", floor($bytes_pct*100), str_repeat("=", round(50*$bytes_pct)), - str_repeat(" ", round(50*(1-$bytes_pct))) + str_repeat(" ", round(50*(1-$bytes_pct))), + $bytes_pct == 1 ? "\n":"" ); }); } - $local = $task->run($this->args->verbose); - $this->debug("\n"); + $local = $task->run($this->verbosity()); - $this->cleanup[] = $local; + $this->cleanup[] = new Task\Cleanup($local); return $local; } @@ -182,9 +170,9 @@ class Packager implements Command $this->debug("Extracting %s ...\n", $source); $task = new Task\Extract($source); - $dest = $task->run($this->args->verbose); + $dest = $task->run($this->verbosity()); - $this->cleanup[] = $dest; + $this->cleanup[] = new Task\Cleanup($dest); return $dest; } @@ -196,21 +184,47 @@ class Packager implements Command private function localize($source) { if (!stream_is_local($source)) { $source = $this->download($source); - $this->cleanup[] = $source; + $this->cleanup[] = new Task\Cleanup($source); } $source = realpath($source); if (!is_dir($source)) { $source = $this->extract($source); - $this->cleanup[] = $source; + $this->cleanup[] = new Task\Cleanup($source); if ($this->args->pecl) { $this->debug("Sanitizing PECL dir ...\n"); - $source = (new Task\PeclFixup($source))->run($this->args->verbose); + $source = (new Task\PeclFixup($source))->run($this->verbosity()); } } return $source; } + /** + * Load the source dir + * @throws \pharext\Exception + */ + private function loadSource(){ + if ($this->args["source"]) { + $source = $this->localize($this->args["source"]); + + if ($this->args["pecl"]) { + $this->source = new SourceDir\Pecl($source); + } elseif ($this->args["git"]) { + $this->source = new SourceDir\Git($source); + } elseif (is_file("$source/parext_package.php")) { + $this->source = include "$source/pharext_package.php"; + } + + if (!$this->source instanceof SourceDir) { + throw new Exception("Unknown source dir $source"); + } + + foreach ($this->source->getPackageInfo() as $key => $val) { + $this->args->$key = $val; + } + } + } + /** * Creates the extension phar */ @@ -233,9 +247,9 @@ class Packager implements Command try { if ($this->args->sign) { $this->info("Using private key to sign phar ...\n"); - $pass = (new Task\Askpass)->run($this->args->verbose); + $pass = (new Task\Askpass)->run($this->verbosity()); $sign = new Task\PharSign($file, $this->args->sign, $pass); - $pkey = $sign->run($this->args->verbose); + $pkey = $sign->run($this->verbosity()); } } catch (\Exception $e) { @@ -247,13 +261,13 @@ class Packager implements Command try { $gzip = (new Task\PharCompress($file, Phar::GZ))->run(); $move = new Task\PharRename($gzip, $this->args->dest, $this->args->name ."-". $this->args->release); - $name = $move->run($this->args->verbose); + $name = $move->run($this->verbosity()); $this->info("Created gzipped phar %s\n", $name); if ($this->args->sign) { $sign = new Task\PharSign($name, $this->args->sign, $pass); - $sign->run($this->args->verbose)->exportPublicKey($name.".pubkey"); + $sign->run($this->verbosity())->exportPublicKey($name.".pubkey"); } } catch (\Exception $e) { @@ -265,13 +279,13 @@ class Packager implements Command try { $bzip = (new Task\PharCompress($file, Phar::BZ2))->run(); $move = new Task\PharRename($bzip, $this->args->dest, $this->args->name ."-". $this->args->release); - $name = $move->run($this->args->verbose); + $name = $move->run($this->verbosity()); $this->info("Created bzipped phar %s\n", $name); if ($this->args->sign) { $sign = new Task\PharSign($name, $this->args->sign, $pass); - $sign->run($this->args->verbose)->exportPublicKey($name.".pubkey"); + $sign->run($this->verbosity())->exportPublicKey($name.".pubkey"); } } catch (\Exception $e) { @@ -281,7 +295,7 @@ class Packager implements Command try { $move = new Task\PharRename($file, $this->args->dest, $this->args->name ."-". $this->args->release); - $name = $move->run($this->args->verbose); + $name = $move->run($this->verbosity()); $this->info("Created executable phar %s\n", $name); diff --git a/src/pharext/SourceDir.php b/src/pharext/SourceDir.php index fbdd2f6..8620668 100644 --- a/src/pharext/SourceDir.php +++ b/src/pharext/SourceDir.php @@ -3,24 +3,31 @@ namespace pharext; /** - * Source directory interface + * Source directory interface, which should yield file names to package on traversal */ interface SourceDir extends \Traversable { - /** - * Read the source directory - * - * Note: Best practices are for others, but if you want to follow them, do - * not put constructors in interfaces. Keep your complaints, I warned you. - * - * @param Command $cmd - * @param string $path - */ - public function __construct(Command $cmd, $path); - /** * Retrieve the base directory * @return string */ public function getBaseDir(); + + /** + * Retrieve gathered package info + * @return array|Traversable + */ + public function getPackageInfo(); + + /** + * Provide installer command line args + * @return array|Traversable + */ + public function getArgs(); + + /** + * Process installer command line args + * @param \pharext\Cli\Args $args + */ + public function setArgs(Cli\Args $args); } diff --git a/src/pharext/SourceDir/Git.php b/src/pharext/SourceDir/Git.php index 8e35bf9..e17a305 100644 --- a/src/pharext/SourceDir/Git.php +++ b/src/pharext/SourceDir/Git.php @@ -3,6 +3,7 @@ namespace pharext\SourceDir; use pharext\Command; +use pharext\Cli\Args; use pharext\SourceDir; /** @@ -10,12 +11,6 @@ use pharext\SourceDir; */ class Git implements \IteratorAggregate, SourceDir { - /** - * The Packager command - * @var pharext\Command - */ - private $cmd; - /** * Base directory * @var string @@ -26,8 +21,7 @@ class Git implements \IteratorAggregate, SourceDir * @inheritdoc * @see \pharext\SourceDir::__construct() */ - public function __construct(Command $cmd, $path) { - $this->cmd = $cmd; + public function __construct($path) { $this->path = $path; } @@ -38,7 +32,29 @@ class Git implements \IteratorAggregate, SourceDir public function getBaseDir() { return $this->path; } - + + /** + * @inheritdoc + * @return array + */ + public function getPackageInfo() { + return []; + } + + /** + * @inheritdoc + * @return array + */ + public function getArgs() { + return []; + } + + /** + * @inheritdoc + */ + public function setArgs(Args $args) { + } + /** * Generate a list of files by `git ls-files` * @return Generator @@ -50,13 +66,7 @@ class Git implements \IteratorAggregate, SourceDir $path = realpath($this->path); while (!feof($pipe)) { if (strlen($file = trim(fgets($pipe)))) { - if ($this->cmd->getArgs()->verbose) { - $this->cmd->info("Packaging %s\n", $file); - } /* there may be symlinks, so no realpath here */ - if (!file_exists("$path/$file")) { - $this->cmd->warn("File %s does not exist in %s\n", $file, $path); - } yield "$path/$file"; } } @@ -64,7 +74,7 @@ class Git implements \IteratorAggregate, SourceDir } chdir($pwd); } - + /** * Implements IteratorAggregate * @see IteratorAggregate::getIterator() diff --git a/src/pharext/SourceDir/Pecl.php b/src/pharext/SourceDir/Pecl.php index 9ca9726..188ea67 100644 --- a/src/pharext/SourceDir/Pecl.php +++ b/src/pharext/SourceDir/Pecl.php @@ -2,21 +2,16 @@ namespace pharext\SourceDir; -use pharext\Command; +use pharext\Cli\Args; use pharext\Exception; use pharext\SourceDir; +use pharext\Tempfile; /** * A PECL extension source directory containing a v2 package.xml */ class Pecl implements \IteratorAggregate, SourceDir { - /** - * The Packager command - * @var pharext\Packager - */ - private $cmd; - /** * The package.xml * @var SimpleXmlElement @@ -28,44 +23,28 @@ class Pecl implements \IteratorAggregate, SourceDir * @var string */ private $path; + + /** + * The package.xml + * @var string + */ + private $file; /** * @inheritdoc * @see \pharext\SourceDir::__construct() */ - public function __construct(Command $cmd, $path) { - if (realpath("$path/package2.xml")) { - $sxe = simplexml_load_file("$path/package2.xml"); - } elseif (realpath("$path/package.xml")) { - $sxe = simplexml_load_file("$path/package.xml"); + public function __construct($path) { + if (is_file("$path/package2.xml")) { + $sxe = simplexml_load_file($this->file = "$path/package2.xml"); + } elseif (is_file("$path/package.xml")) { + $sxe = simplexml_load_file($this->file = "$path/package.xml"); } else { throw new Exception("Missing package.xml in $path"); } - $sxe->registerXPathNamespace("pecl", $sxe->getDocNamespaces()[""]); - - $args = $cmd->getArgs(); - if (!isset($args->name)) { - $name = (string) $sxe->xpath("/pecl:package/pecl:name")[0]; - foreach ($args->parse(2, ["--name", $name]) as $error) { - $cmd->warn("%s\n", $error); - } - } - if (!isset($args->release)) { - $release = (string) $sxe->xpath("/pecl:package/pecl:version/pecl:release")[0]; - foreach ($args->parse(2, ["--release", $release]) as $error) { - $cmd->warn("%s\n", $error); - } - } - if (!isset($args->zend)) { - if ($sxe->xpath("/pecl:package/pecl:zendextsrcrelease")) { - foreach ($args->parse(1, ["--zend"]) as $error) { - $cmd->warn("%s\n", $error); - } - } - } + $sxe->registerXPathNamespace("pecl", $sxe->getDocNamespaces()[""]); - $this->cmd = $cmd; $this->sxe = $sxe; $this->path = $path; } @@ -77,6 +56,58 @@ class Pecl implements \IteratorAggregate, SourceDir public function getBaseDir() { return $this->path; } + + /** + * Retrieve gathered package info + * @return Generator + */ + public function getPackageInfo() { + if (($name = $this->sxe->xpath("/pecl:package/pecl:name"))) { + yield "name" => (string) $name[0]; + } + if (($release = $this->sxe->xpath("/pecl:package/pecl:version/pecl:release"))) { + yield "release" => (string) $release[0]; + } + if ($this->sxe->xpath("/pecl:package/pecl:zendextsrcrelease")) { + yield "zend" => true; + } + } + + /** + * @inheritdoc + * @see \pharext\SourceDir::getArgs() + */ + public function getArgs() { + $configure = $this->sxe->xpath("/pecl:package/pecl:extsrcrelease/pecl:configureoption"); + foreach ($configure as $cfg) { + yield [null, $cfg["name"], ucfirst($cfg["prompt"]), Args::OPTARG, + strlen($cfg["default"]) ? $cfg["default"] : null]; + } + $configure = $this->sxe->xpath("/pecl:package/pecl:zendextsrcrelease/pecl:configureoption"); + foreach ($configure as $cfg) { + yield [null, $cfg["name"], ucfirst($cfg["prompt"]), Args::OPTARG, + strlen($cfg["default"]) ? $cfg["default"] : null]; + } + } + + /** + * @inheritdoc + * @see \pharext\SourceDir::setArgs() + */ + public function setArgs(Args $args) { + $configure = $this->sxe->xpath("/pecl:package/pecl:extsrcrelease/pecl:configureoption"); + foreach ($configure as $cfg) { + if (isset($args[$cfg["name"]])) { + $args->configure = "--{$cfg["name"]}={$args[$cfg["name"]]}"; + } + } + $configure = $this->sxe->xpath("/pecl:package/pecl:zendextsrcrelease/pecl:configureoption"); + foreach ($configure as $cfg) { + if (isset($args[$cfg["name"]])) { + $args->configure = "--{$cfg["name"]}={$args[$cfg["name"]]}"; + } + } + } /** * Compute the path of a file by parent dir nodes @@ -92,20 +123,17 @@ class Pecl implements \IteratorAggregate, SourceDir } /** - * Render installer hook - * @param array $configure - * @return string + * Generate a list of files from the package.xml + * @return Generator */ - private static function loadHook($configure, $dependencies) { - require_once "pharext/Version.php"; - return include __DIR__."/../../pharext_install.tpl.php"; - } + private function generateFiles() { + /* hook */ + $temp = tmpfile(); + fprintf($temp, " $temp; - /** - * Create installer hook - * @return \Generator - */ - private function generateHooks() { + /* deps */ $dependencies = $this->sxe->xpath("/pecl:package/pecl:dependencies/pecl:required/pecl:package"); foreach ($dependencies as $key => $dep) { if (($glob = glob("{$this->path}/{$dep->name}-*.ext.phar*"))) { @@ -116,44 +144,13 @@ class Pecl implements \IteratorAggregate, SourceDir ); }); yield end($glob); - } else { - unset($dependencies[$key]); - } - } - $configure = $this->sxe->xpath("/pecl:package/pecl:extsrcrelease/pecl:configureoption"); - if ($configure) { - $fd = tmpfile(); - ob_start(function($s) use($fd){ - fwrite($fd, $s); - return null; - }); - self::loadHook($configure, $dependencies); - ob_end_flush(); - rewind($fd); - yield "pharext_install.php" => $fd; - } - } - - /** - * Generate a list of files from the package.xml - * @return Generator - */ - private function generateFiles() { - foreach ($this->generateHooks() as $file => $hook) { - if ($this->cmd->getArgs()->verbose) { - $this->cmd->info("Packaging %s\n", is_scalar($hook) ? $hook : $file); } - yield $file => $hook; } + + /* files */ + yield $this->file; foreach ($this->sxe->xpath("//pecl:file") as $file) { - $path = $this->path ."/". $this->dirOf($file) ."/". $file["name"]; - if ($this->cmd->getArgs()->verbose) { - $this->cmd->info("Packaging %s\n", substr($path, strlen($this->path))); - } - if (!($realpath = realpath($path))) { - $this->cmd->warn("File %s does not exist", $path); - } - yield $realpath; + yield realpath($this->path ."/". $this->dirOf($file) ."/". $file["name"]); } } diff --git a/src/pharext/SourceDir/Pharext.php b/src/pharext/SourceDir/Pharext.php deleted file mode 100644 index 8ca0901..0000000 --- a/src/pharext/SourceDir/Pharext.php +++ /dev/null @@ -1,62 +0,0 @@ -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); - } - - /** - * @inheritdoc - * @see \pharext\SourceDir::getBaseDir() - */ - public function getBaseDir() { - return $this->path; - } - - /** - * Implements IteratorAggregate - * @see IteratorAggregate::getIterator() - */ - public function getIterator() { - if (!is_callable($this->iter)) { - return new Git($this->cmd, $this->path); - } - return call_user_func($this->iter, $this->cmd, $this->path); - } -} diff --git a/src/pharext/Task/Cleanup.php b/src/pharext/Task/Cleanup.php new file mode 100644 index 0000000..1263bd9 --- /dev/null +++ b/src/pharext/Task/Cleanup.php @@ -0,0 +1,47 @@ +rm = $rm; + } + + /** + * @param bool $verbose + */ + public function run($verbose = false) { + if (is_dir($this->rm)) { + $rdi = new RecursiveDirectoryIterator($this->rm, + FilesystemIterator::CURRENT_AS_PATHNAME | + FilesystemIterator::SKIP_DOTS); + $rii = new RecursiveIteratorIterator($rdi, + RecursiveIteratorIterator::CHILD_FIRST); + foreach ($rii as $path) { + if ($rii->isDir()) { + rmdir($path); + } else { + unlink($path); + } + } + rmdir($this->rm); + } else { + @unlink($this->rm); + } + } +} diff --git a/src/pharext_install.tpl.php b/src/pharext_install.tpl.php deleted file mode 100644 index f7a356d..0000000 --- a/src/pharext_install.tpl.php +++ /dev/null @@ -1,38 +0,0 @@ - - -/** - * Generated by pharext v at . - */ -namespace pharext; - -use pharext\Cli\Args as CliArgs; - -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/GitSourceDirTest.php b/tests/src/pharext/GitSourceDirTest.php index 5e6a989..ac04d4d 100644 --- a/tests/src/pharext/GitSourceDirTest.php +++ b/tests/src/pharext/GitSourceDirTest.php @@ -25,7 +25,7 @@ class GitSourceDirTest extends \PHPUnit_Framework_TestCase protected $source; protected function setUp() { - $this->source = new SourceDir\Git(new Cmd, "."); + $this->source = new SourceDir\Git("."); } public function testGetBaseDir() { diff --git a/tests/src/pharext/TaskTest.php b/tests/src/pharext/TaskTest.php new file mode 100644 index 0000000..cb11377 --- /dev/null +++ b/tests/src/pharext/TaskTest.php @@ -0,0 +1,71 @@ +run(); + + $this->assertTrue(is_dir("$dir/.git"), "is_dir($dir/.git)"); + + (new Task\Cleanup($dir))->run(); + $this->assertFalse(is_dir($dir), "is_dir($dir)"); + } + + function testPecl() { + $cmd = new Task\StreamFetch("http://pecl.php.net/get/pecl_http", function($pct) use(&$log) { + $log[] = $pct; + }); + $tmp = $cmd->run(); + + $this->assertTrue(is_file($tmp), "is_file($tmp)"); + $this->assertGreaterThan(1, count($log), "1 < count(\$log)"); + $this->assertContains(0, $log, "in_array(0, \$log)"); + $this->assertContains(1, $log, "in_array(1, \$log)"); + + $cmd = new Task\Extract($tmp); + $dir = $cmd->run(); + + $this->assertTrue(is_dir($dir), "is_dir($dir)"); + $this->assertTrue(is_file("$dir/package.xml"), "is_file($dir/package.xml"); + + $cmd = new Task\PeclFixup($dir); + $new = $cmd->run(); + + $this->assertTrue(is_dir($new), "is_dir($new)"); + $this->assertFalse(is_file("$dir/package.xml"), "is_file($dir/package.xml"); + $this->assertTrue(is_file("$new/package.xml"), "is_file($new/package.xml"); + + (new Task\Cleanup($dir))->run(); + $this->assertFalse(is_dir($dir), "is_dir($dir)"); + $this->assertFalse(is_dir($new), "is_dir($new)"); + } + + function testPackage() { + $tmp = (new Task\StreamFetch("http://pecl.php.net/get/json_post/1.0.0", function(){}))->run(); + $dir = (new Task\Extract($tmp))->run(); + $new = (new Task\PeclFixup($dir))->run(); + $src = new SourceDir\Pecl($new); + $inf = [ + "date" => date("Y-m-d"), + "name" => "json_post", + "release" => "1.0.0", + "license" => file_get_contents($src->getBaseDir()."/LICENSE"), + "stub" => "pharext_installer.php", + "type" => "extension", + ]; + $pkg = (new Task\PharBuild($src, $inf))->run(); + $gzp = (new Task\PharCompress($pkg, \Phar::GZ))->run(); + $pkg = (new Task\PharRename($pkg, ".", "json_post-1.0.0"))->run(); + $gzp = (new Task\PharRename($gzp, ".", "json_post-1.0.0"))->run(); + + $this->assertTrue(is_file($pkg), "is_file($pkg)"); + $this->assertTrue(is_file($gzp), "is_file($gzp)"); + } +}