add Cli\Args\Help
[pharext/pharext] / src / pharext / Cli / Command.php
index 706cb850efd29c58510fc3d7916f43f4c7689fb4..b733885a26a9c39e52d1d15544a2a631b2e889ce 100644 (file)
@@ -4,7 +4,21 @@ namespace pharext\Cli;
 
 use pharext\Cli\Args as CliArgs;
 
-require_once "pharext/Version.php";
+use Phar;
+
+if (!function_exists("array_column")) {
+       function array_column(array $array, $col, $idx = null) {
+               $result = [];
+               foreach ($array as $el) {
+                       if (isset($idx)) {
+                               $result[$el[$idx]] = $el[$col];
+                       } else {
+                               $result[] = $el[$col];
+                       }
+               }
+               return $result;
+       }
+}
 
 trait Command
 {
@@ -22,12 +36,47 @@ trait Command
                return $this->args;
        }
 
+       /**
+        * Retrieve metadata of the currently running phar
+        * @param string $key
+        * @return mixed
+        */
+       public function metadata($key = null) {
+               $running = new Phar(Phar::running(false));
+
+               if ($key === "signature") {
+                       $sig = $running->getSignature();
+                       return sprintf("%s signature of %s\n%s", 
+                               $sig["hash_type"],
+                               $this->metadata("name"),
+                               chunk_split($sig["hash"], 64, "\n"));
+               }
+
+               $metadata = $running->getMetadata();
+               if (isset($key)) {
+                       return $metadata[$key];
+               }
+               return $metadata;
+       }
+
        /**
         * Output pharext vX.Y.Z header
         */
-       function header() {
-               printf("pharext v%s (c) Michael Wallner <mike@php.net>\n\n", 
-                       \pharext\VERSION);
+       public function header() {
+               if (!headers_sent()) {
+                       /* only display header, if we didn't generate any output yet */
+                       printf("%s\n\n", $this->metadata("header"));
+               }
+       }
+       
+       /**
+        * @inheritdoc
+        * @see \pharext\Command::debug()
+        */
+       public function debug($fmt) {
+               if ($this->args->verbose) {
+                       vprintf($fmt, array_slice(func_get_args(), 1));
+               }
        }
        
        /**
@@ -42,9 +91,9 @@ trait Command
 
        /**
         * @inheritdoc
-        * @see \pharext\Command::error()
+        * @see \pharext\Command::warn()
         */
-       public function error($fmt) {
+       public function warn($fmt) {
                if (!$this->args->quiet) {
                        if (!isset($fmt)) {
                                $fmt = "%s\n";
@@ -52,185 +101,43 @@ trait Command
                        } else {
                                $arg = array_slice(func_get_args(), 1);
                        }
-                       vfprintf(STDERR, "ERROR: $fmt", $arg);
+                       vfprintf(STDERR, "Warning: $fmt", $arg);
                }
        }
 
        /**
-        * Output command line help message
-        * @param string $prog
-        */
-       public function help($prog) {
-               printf("Usage:\n\n  \$ %s", $prog);
-               
-               $flags = [];
-               $required = [];
-               $optional = [];
-               foreach ($this->args->getSpec() as $spec) {
-                       if ($spec[3] & CliArgs::REQARG) {
-                               if ($spec[3] & CliArgs::REQUIRED) {
-                                       $required[] = $spec;
-                               } else {
-                                       $optional[] = $spec;
-                               }
-                       } else {
-                               $flags[] = $spec;
-                       }
-               }
-       
-               if ($flags) {
-                       printf(" [-%s]", implode("", array_column($flags, 0)));
-               }
-               foreach ($required as $req) {
-                       printf(" -%s <arg>", $req[0]);
-               }
-               if ($optional) {
-                       printf(" [-%s <arg>]", implode("|-", array_column($optional, 0)));
-               }
-               printf("\n\n");
-               $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("<arg>  ");
-                       } elseif ($spec[3] & CliArgs::OPTARG) {
-                               printf("[<arg>]");
-                       } 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]);
-                       }
-                       printf("\n");
-               }
-               printf("\n");
-       }
-       
-       /**
-        * Create temporary file/directory name
-        * @param string $prefix
-        * @param string $suffix
-        */
-       private function tempname($prefix, $suffix = null) {
-               if (!isset($suffix)) {
-                       $suffix = uniqid();
-               }
-               return sprintf("%s/%s.%s", sys_get_temp_dir(), $prefix, $suffix);
-       }
-
-       /**
-        * Create a new temp directory
-        * @param string $prefix
-        * @return string
-        */
-       private function newtemp($prefix) {
-               $temp = $this->tempname($prefix);
-               if (!is_dir($temp)) {
-                       if (!mkdir($temp, 0700, true)) {
-                               $this->error(null);
-                               exit(3);
-                       }
-               }
-               return $temp;
-       }
-
-       /**
-        * rm -r
-        * @param string $dir
+        * @inheritdoc
+        * @see \pharext\Command::error()
         */
-       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->error(null);
-                       }
-               }
-               if (!rmdir($dir)) {
-                       $this->error(null);
+       public function error($fmt) {
+               if (!isset($fmt)) {
+                       $fmt = "%s\n";
+                       $arg = error_get_last()["message"];
+               } else {
+                       $arg = array_slice(func_get_args(), 1);
                }
+               vfprintf(STDERR, "ERROR: $fmt", $arg);
        }
 
        /**
-        * Execute a program with escalated privileges handling interactive password prompt
-        * @param string $command
-        * @param string $output
-        * @return int
+        * Output command line help message
+        * @param string $prog
         */
-       private function sudo($command, &$output) {
-               if (!($proc = proc_open($command, [STDIN,["pipe","w"],["pipe","w"]], $pipes))) {
-                       return -1;
-               }
-               $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;
-               }
-               return proc_close($proc);
+       public function help($prog) {
+               print new Args\Help($prog, $this->args);
        }
-
+       
        /**
-        * Execute a system command
-        * @param string $name pretty name
-        * @param string $command command
-        * @param array $args command arguments
-        * @param bool $sudo whether the command may need escalated privileges
+        * Verbosity
+        * @return boolean
         */
-       private function exec($name, $command, array $args = null, $sudo = false) {
-               $exec = escapeshellcmd($command);
-               if ($args) {
-                       $exec .= " ". implode(" ", array_map("escapeshellarg", (array) $args));
-               }
-
+       public function verbosity() {
                if ($this->args->verbose) {
-                       $this->info("Running %s ...\n", $exec);
-               } else {
-                       $this->info("Running %s ... ", $name);
-               }
-
-               if ($sudo && isset($this->args->sudo)) {
-                       $retval = $this->sudo(sprintf($this->args->sudo." 2>&1", $exec), $output);
-               } elseif ($this->args->verbose) {
-                       passthru($exec ." 2>&1", $retval);
+                       return true;
+               } elseif ($this->args->quiet) {
+                       return false;
                } else {
-                       exec($exec ." 2>&1", $output, $retval);
-                       $output = implode("\n", $output);
-               }
-
-               if ($retval) {
-                       $this->error("Command %s failed with (%s)\n", $command, $retval);
-                       if (isset($output) && !$this->args->quiet) {
-                               printf("%s\n", $output);
-                       }
-                       exit(2);
-               }
-               if (!$this->args->verbose) {
-                       // we already have a bunch of output
-                       $this->info("OK\n");
+                       return null;
                }
        }
 }