/tools/src/main/php/xp/xar/Runner.class.php

https://github.com/oanas/xp-framework · PHP · 196 lines · 83 code · 12 blank · 101 comment · 12 complexity · cce0a2324f6059c90aaec9ed5f796234 MD5 · raw file

  1. <?php
  2. /* This class is part of the XP framework
  3. *
  4. * $Id$
  5. */
  6. $package= 'xp.xar';
  7. uses('util.cmd.Console', 'xp.xar.Options', 'io.File');
  8. /**
  9. * XAR
  10. * ===
  11. * This tool can be used for working with XAR archives.
  12. *
  13. * Usage:
  14. * <pre>
  15. * $ xar {options} {xarfile} [{fileset}]
  16. * </pre>
  17. *
  18. * Option synopsis
  19. * ===============
  20. * -c Create archive
  21. * -x Extract archive
  22. * -t List archive contents
  23. * -s See file`s contents
  24. * -d Diff archives
  25. * -m Merge archives
  26. *
  27. *
  28. * Command details
  29. * ===============
  30. *
  31. * Creating a xar file
  32. * -------------------
  33. * The following creates a xar file containing all files inside the
  34. * directories "src" and "lib" as well as the file "etc/config.ini".
  35. *
  36. * <tt>$ xar cf app.xar src/ lib/ etc/config.ini</tt>
  37. *
  38. *
  39. * Extracting a xar file
  40. * ---------------------
  41. * The following extracts all files inside the "app.xar" into the
  42. * current directory. Directories and files are created if necessary,
  43. * existing files are overwritten.
  44. *
  45. * <tt>$ xar xf app.xar</tt>
  46. *
  47. *
  48. * Viewing an archive's contents
  49. * -----------------------------
  50. * To list what's inside a xar file, use the following command:
  51. *
  52. * <tt>$ xar tf app.xar</tt>
  53. *
  54. *
  55. * Viewing the contents of a contained file
  56. * ----------------------------------------
  57. * To view a single file from a given archive, use the following command:
  58. *
  59. * <tt>$ xar sf archive.xar path/to/file/in/archive</tt>
  60. *
  61. *
  62. * Merging multiple archives
  63. * -------------------------
  64. * To merge archives into a single new one, use the following command:
  65. *
  66. * <tt>$ xar mf new.xar old-archive-1.xar old-archive-2.xar</tt>
  67. *
  68. *
  69. * Comparing two archives
  70. * ----------------------
  71. * To compare two archives, use the following command:
  72. *
  73. * <tt>$ xar df one.xar two.xar</tt>
  74. *
  75. * @purpose Tool
  76. */
  77. class xp·xar·Runner extends Object {
  78. /**
  79. * Set operation
  80. *
  81. * @param xp.xar.instruction.AbstractInstruction operation
  82. * @param string name
  83. */
  84. protected static function setOperation(&$operation, $name) {
  85. if (NULL !== $operation) {
  86. self::bail('Cannot execute more than one instruction at a time.');
  87. }
  88. $operation= Package::forName('xp.xar.instruction')->loadClass(ucfirst($name).'Instruction');
  89. }
  90. /**
  91. * Converts api-doc "markup" to plain text w/ ASCII "art"
  92. *
  93. * @param string markup
  94. * @return string text
  95. */
  96. protected static function textOf($markup) {
  97. $line= str_repeat('=', 72);
  98. return strip_tags(preg_replace(array(
  99. '#<pre>#', '#</pre>#', '#<li>#',
  100. ), array(
  101. $line, $line, '* ',
  102. ), trim($markup)));
  103. }
  104. /**
  105. * Displays usage and exists
  106. *
  107. */
  108. protected static function usage() {
  109. Console::$err->writeLine(self::textOf(XPClass::forName(xp::nameOf(__CLASS__))->getComment()));
  110. exit(1);
  111. }
  112. /**
  113. * Displays a message and exists
  114. *
  115. */
  116. protected static function bail($message) {
  117. Console::$err->writeLine('*** ', $message);
  118. exit(1);
  119. }
  120. /**
  121. * Main runner method
  122. *
  123. * @param string[] args
  124. */
  125. public static function main(array $args) {
  126. if (!$args) self::usage();
  127. // Parse command line
  128. $operation= NULL;
  129. $std= 'php://stdin';
  130. for ($i= 0; $i < sizeof($args); $i++) {
  131. if ('-R' == $args[$i]) {
  132. chdir($args[++$i]);
  133. } else if (in_array($args[$i], array('-?', '-h', '--help'))) {
  134. self::usage();
  135. } else {
  136. $options= 0;
  137. $offset= $i;
  138. for ($o= 0; $o < strlen($args[$i]); $o++) {
  139. switch ($args[$i]{$o}) {
  140. case 'c':
  141. self::setOperation($operation, 'create');
  142. $std= 'php://stdout';
  143. break;
  144. case 'x':
  145. self::setOperation($operation, 'extract');
  146. break;
  147. case 's':
  148. self::setOperation($operation, 'show');
  149. break;
  150. case 'd':
  151. self::setOperation($operation, 'diff');
  152. break;
  153. case 't':
  154. self::setOperation($operation, 'extract');
  155. $options |= Options::SIMULATE | Options::VERBOSE;
  156. break;
  157. case 'm':
  158. self::setOperation($operation, 'merge');
  159. $std= 'php://stdout';
  160. break;
  161. case 'v':
  162. $options |= Options::VERBOSE;
  163. break;
  164. case 'f':
  165. $file= new File($args[$i+ 1]);
  166. $std= NULL;
  167. $offset++;
  168. break;
  169. default:
  170. self::bail('Unsupported commandline option "'.$args[$i].'"');
  171. }
  172. }
  173. $args= array_slice($args, $offset+ 1);
  174. break;
  175. }
  176. }
  177. if (!$operation) self::usage();
  178. // Use STDOUT & STDERR if no file is given
  179. if ($std) $file= new File($std);
  180. // Perform operation
  181. $operation->newInstance(Console::$out, Console::$err, $options, new Archive($file), $args)->perform();
  182. }
  183. }
  184. ?>