From: Michael Wallner Date: Sun, 22 Mar 2015 06:08:35 +0000 (+0100) Subject: add ExecCmd and Tempdir X-Git-Tag: v3.0.0~23 X-Git-Url: https://git.m6w6.name/?p=pharext%2Fpharext;a=commitdiff_plain;h=c8adc57c38cc535e0dcda979565b7639896e7370 add ExecCmd and Tempdir --- diff --git a/bin/pharext b/bin/pharext index 7947819..65f4d24 100755 Binary files a/bin/pharext and b/bin/pharext differ diff --git a/src/pharext/ExecCmd.php b/src/pharext/ExecCmd.php new file mode 100644 index 0000000..056f0b2 --- /dev/null +++ b/src/pharext/ExecCmd.php @@ -0,0 +1,134 @@ +command = $command; + $this->verbose = $verbose; + + /* interrupt output stream */ + if ($verbose) { + printf("\n"); + } + } + + /** + * (Re-)set sudo command + * @param string $sudo + */ + public function setSu($sudo = false) { + $this->sudo = $sudo; + } + + /** + * Execute a program with escalated privileges handling interactive password prompt + * @param string $command + * @param string $output + * @param int $status + */ + private function suExec($command, &$output, &$status) { + if (!($proc = proc_open($command, [STDIN,["pipe","w"],["pipe","w"]], $pipes))) { + $status = -1; + throw new \Exception("Failed to run {$command}"); + } + $stdout = $pipes[1]; + $passwd = 0; + while (!feof($stdout)) { + $R = [$stdout]; $W = []; $E = []; + if (!stream_select($R, $W, $E, null)) { + continue; + } + $data = fread($stdout, 0x1000); + /* only check a few times */ + if ($passwd++ < 10) { + if (stristr($data, "password")) { + printf("\n%s", $data); + } + } + $output .= $data; + } + $status = proc_close($proc); + } + + /** + * Run the command + * @param array $args + * @throws \Exception + */ + public function run(array $args = null) { + $exec = escapeshellcmd($this->command); + if ($args) { + $exec .= " ". implode(" ", array_map("escapeshellarg", (array) $args)); + } + + if ($this->sudo) { + $this->suExec(sprintf($this->sudo." 2>&1", $exec), $this->output, $this->status); + } elseif ($this->verbose) { + ob_start(function($s) { + $this->output .= $s; + return $s; + }, 1); + passthru($exec, $this->status); + ob_end_flush(); + } else { + exec($exec ." 2>&1", $output, $this->status); + $this->output = implode("\n", $output); + } + + if ($this->status) { + throw new \Exception("Command {$this->command} failed ({$this->status})"); + } + } + + /** + * Retrieve exit code of cmd run + * @return int + */ + public function getStatus() { + return $status; + } + + /** + * Retrieve output of cmd run + * @return string + */ + public function getOutput() { + return $this->output; + } +} diff --git a/src/pharext/Installer.php b/src/pharext/Installer.php index 5e86f31..b41d7fd 100644 --- a/src/pharext/Installer.php +++ b/src/pharext/Installer.php @@ -69,7 +69,7 @@ class Installer implements Command $phar = new Phar(Phar::running(false)); foreach ($phar as $entry) { if (fnmatch("*.ext.phar*", $entry->getBaseName())) { - $temp = $this->newtemp($entry->getBaseName()); + $temp = new Tempdir($entry->getBaseName()); $phar->extractTo($temp, $entry->getFilename(), true); $phars[$temp] = new Phar($temp."/".$entry->getFilename()); } @@ -140,37 +140,58 @@ class Installer implements Command $this->error(null); exit(4); } - - // phpize - $this->exec("phpize", $this->php("ize")); - - // configure - $args = ["--with-php-config=". $this->php("-config")]; - if ($this->args->configure) { - $args = array_merge($args, $this->args->configure); - } - $this->exec("configure", "./configure", $args); - - // make - if ($this->args->verbose) { - $this->exec("make", "make", ["-j3"]); - } else { - $this->exec("make", "make", ["-j3", "-s"]); - } - - // install - if ($this->args->verbose) { - $this->exec("install", "make", ["install"], true); - } else { - $this->exec("install", "make", ["install", "-s"], true); - } - - // activate + + $this->build(); $this->activate(); - - // cleanup $this->cleanup($temp); } + + /** + * Phpize + trinity + */ + private function build() { + try { + // phpize + $this->info("Runnin phpize ... "); + $cmd = new ExecCmd($this->php("ize"), $this->args->verbose); + $cmd->run(); + $this->info("OK\n"); + + // configure + $this->info("Running configure ... "); + $args = ["--with-php-config=". $this->php("-config")]; + if ($this->args->configure) { + $args = array_merge($args, $this->args->configure); + } + $cmd = new ExecCmd("./configure", $this->args->verbose); + $cmd->run($args); + $this->info("OK\n"); + + // make + $this->info("Running make ... "); + $cmd = new ExecCmd("make", $this->args->verbose); + if ($this->args->verbose) { + $cmd->run(["-j3"]); + } else { + $cmd->run(["-j3", "-s"]); + } + $this->info("OK\n"); + + // install + $this->info("Running make install ... "); + $cmd->setSu($this->args->sudo); + if ($this->args->verbose) { + $cmd->run(["install"]); + } else { + $cmd->run(["install", "-s"]); + } + $this->info("OK\n"); + + } catch (\Exception $e) { + $this->error("%s\n", $e->getMessage()); + $this->error("%s\n", $cmd->getOutput()); + } + } /** * Perform any cleanups @@ -233,13 +254,31 @@ class Installer implements Command $path = $temp->getPathname(); $stat = stat($file); - $ugid = sprintf("%d:%d", $stat["uid"], $stat["gid"]); - $this->exec("INI owner transfer", "chown", [$ugid, $path], true); - - $perm = decoct($stat["mode"] & 0777); - $this->exec("INI permission transfer", "chmod", [$perm, $path], true); - - $this->exec("INI activation", "mv", [$path, $file], true); + try { + $this->info("Running INI owner transfer ... "); + $ugid = sprintf("%d:%d", $stat["uid"], $stat["gid"]); + $cmd = new ExecCmd("chown", $this->args->verbose); + $cmd->setSu($this->args->sudo); + $cmd->run([$ugid, $path]); + $this->info("OK\n"); + + $this->info("Running INI permission transfer ... "); + $perm = decoct($stat["mode"] & 0777); + $cmd = new ExecCmd("chmod", $this->args->verbose); + $cmd->setSu($this->args->sudo); + $cmd->run([$perm, $path]); + $this->info("OK\n"); + + $this->info("Running INI activation ... "); + $cmd = new ExecCmd("mv", $this->args->verbose); + $cmd->setSu($this->args->sudo); + $cmd->run([$path, $file]); + $this->info("OK\n"); + } catch (\Exception $e) { + $this->error("%s\n", $e->getMessage()); + $this->error("%s\n", $cmd->getOutput()); + exit(5); + } } } } diff --git a/src/pharext/Packager.php b/src/pharext/Packager.php index 33aa72e..d66e83b 100644 --- a/src/pharext/Packager.php +++ b/src/pharext/Packager.php @@ -95,6 +95,10 @@ class Packager implements Command } try { + /* source needs to be evaluated before CliArgs validation, + * 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"]) { @@ -115,7 +119,10 @@ class Packager implements Command if ($errs) { if (!$this->args["quiet"]) { - $this->header(); + if (!headers_sent()) { + /* only display header, if we didn't generate any output yet */ + $this->header(); + } } foreach ($errs as $err) { $this->error("%s\n", $err); @@ -154,9 +161,13 @@ class Packager implements Command */ private function download($source) { if ($this->args["git"]) { - $local = $this->newtemp("gitclone"); - $this->exec("git clone", "git", ["clone", $source, $local]); - $source = $local; + $this->info("Cloning %s ... ", $source); + $local = new Tempdir("gitclone"); + $cmd = new ExecCmd("git", $this->args->verbose); + $cmd->run(["clone", $source, $local]); + if (!$this->args->verbose) { + $this->info("OK\n"); + } } else { $this->info("Fetching remote source %s ... ", $source); if (!$remote = fopen($source, "r")) { @@ -169,12 +180,11 @@ class Packager implements Command exit(2); } $local->closeStream(); - $source = $local->getPathname(); $this->info("OK\n"); } $this->cleanup[] = $local; - return $source; + return $local->getPathname(); } /** @@ -183,8 +193,10 @@ class Packager implements Command * @return string extracted directory */ private function extract($source) { - $dest = $this->newtemp("local"); - $this->info("Extracting to %s ... ", $dest); + $dest = new Tempdir("local"); + if ($this->args->verbose) { + $this->info("Extracting to %s ... ", $dest); + } $archive = new PharData($source); $archive->extractTo($dest); $this->info("OK\n"); diff --git a/src/pharext/Tempdir.php b/src/pharext/Tempdir.php new file mode 100644 index 0000000..585033a --- /dev/null +++ b/src/pharext/Tempdir.php @@ -0,0 +1,18 @@ +