ConvertShell.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. if (!defined('CHMOD_PUBLIC')) {
  3. define('CHMOD_PUBLIC', 0770);
  4. }
  5. App::uses('AppShell', 'Console/Command');
  6. /**
  7. * A convert shell to quickly convert/correct the type of line endings in files.
  8. * It recursivly walks through a specified folder.
  9. * Uses dos2unix >= 6.0 (should contain 3 separate command tools).
  10. *
  11. * Console call:
  12. * dos2unix [-fhkLlqV] [-c convmode] [-o file ...] [-n inputfile outputfile ...]
  13. *
  14. * It is also possible to manually define the binPath (for Windows for example).
  15. *
  16. * @cakephp 2.x
  17. * @author Mark Scherer
  18. * @license MIT
  19. * 2011-11-04 ms
  20. */
  21. class ConvertShell extends AppShell {
  22. /**
  23. * Predefined options
  24. *
  25. * @var array
  26. */
  27. public $modes = array(
  28. 'git' => array('dos2unix', 'unix2dos'), # d2u + u2d
  29. 'd2u' => 'dos2unix', 'u2d' => 'unix2dos', # dos/unix
  30. 'u2m' => 'unix2mac', 'm2u' => 'mac2unix', # unix/mac
  31. 'd2m' => array('dos2unix', 'unix2mac'), 'm2d' => array('mac2unix', 'unix2dos'), # dos/mac
  32. );
  33. /**
  34. * @var string
  35. */
  36. public $binPath;
  37. /**
  38. * Shell startup, prints info message about dry run.
  39. *
  40. * @return void
  41. */
  42. public function startup() {
  43. parent::startup();
  44. $this->binPath = Configure::read('Cli.dos2unixPath');
  45. if ($this->params['dry-run']) {
  46. $this->out(__d('cake_console', '<warning>Dry-run mode enabled!</warning>'), 1, Shell::QUIET);
  47. }
  48. if (false && !$this->_test()) {
  49. $this->out(__d('cake_console', '<warning>dos2unix not available</warning>'), 1, Shell::QUIET);
  50. }
  51. }
  52. /**
  53. * ConvertShell::folder()
  54. *
  55. * @return void
  56. */
  57. public function folder() {
  58. $this->out('Converting folder...');
  59. $folder = APP;
  60. $mode = $this->params['mode'];
  61. if (empty($mode) || !array_key_exists($mode, $this->modes)) {
  62. return $this->error('Invalid mode', 'Please specify d2u, u2d, git (d2u+u2d) ...');
  63. }
  64. if (!empty($this->args)) {
  65. $folder = array_shift($this->args);
  66. $folder = realpath($folder);
  67. }
  68. if (empty($folder)) {
  69. return $this->error('Invalid dir', 'No valid dir given (either absolute or relative to APP)');
  70. }
  71. $this->_convert($folder, $mode);
  72. $this->out('Done!');
  73. }
  74. public function version() {
  75. $this->_test();
  76. }
  77. /**
  78. * ConvertShell::version()
  79. * //TODO: fixme, always outputs right away..
  80. *
  81. * @return void
  82. */
  83. protected function _test() {
  84. ob_start();
  85. exec($this->binPath . 'dos2unix --version', $output, $x);
  86. $output = ob_get_contents();
  87. ob_end_clean();
  88. return !empty($output) && $x === 0;
  89. }
  90. /**
  91. * ConvertShell::_convert()
  92. *
  93. * @param mixed $dir
  94. * @param mixed $mode
  95. * @param mixed $excludes
  96. * @return void
  97. */
  98. protected function _convert($dir, $mode, $excludes = array()) {
  99. $Iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir),
  100. RecursiveIteratorIterator::CHILD_FIRST);
  101. foreach ($Iterator as $path) {
  102. $fullPath = $path->__toString();
  103. $continue = false;
  104. foreach ($excludes as $exclude) {
  105. if (strpos($fullPath, $exclude) === 0) {
  106. $continue = true;
  107. break;
  108. }
  109. }
  110. if ($continue) {
  111. continue;
  112. }
  113. if ($path->isDir()) {
  114. continue;
  115. }
  116. if (strpos($fullPath, DS.'.') !== false) {
  117. continue;
  118. }
  119. if (!empty($this->params['verbose'])) {
  120. $this->out('Converting file: '.$fullPath);
  121. }
  122. if (empty($this->params['dry-run'])) {
  123. ob_start();
  124. $commands = (array)$this->modes[$mode];
  125. foreach ($commands as $command) {
  126. $this->out('Running', 1, Shell::VERBOSE);
  127. system($this->binPath . $command . ' ' . $fullPath, $x);
  128. }
  129. $output = ob_get_contents();
  130. ob_end_clean();
  131. }
  132. }
  133. }
  134. /**
  135. * Get the option parser
  136. *
  137. * @return ConsoleOptionParser
  138. */
  139. public function getOptionParser() {
  140. $subcommandParser = array(
  141. 'options' => array(
  142. 'mode' => array(
  143. 'short' => 'm',
  144. 'help' => __d('cake_console', 'Mode'),
  145. 'default' => '' # auto detect
  146. ),
  147. 'ext' => array(
  148. 'short' => 'e',
  149. 'help' => __d('cake_console', 'Specify extensions [php|txt|...]'),
  150. 'default' => '',
  151. ),
  152. 'dry-run'=> array(
  153. 'short' => 'd',
  154. 'help' => __d('cake_console', 'Dry run the clear command, no files will actually be deleted. Should be combined with verbose!'),
  155. 'boolean' => true
  156. ),
  157. 'exclude'=> array(
  158. 'short' => 'x',
  159. 'help' => __d('cake_console', 'exclude the following files or folders'),
  160. 'boolean' => true,
  161. 'default' => ''
  162. )
  163. )
  164. );
  165. return parent::getOptionParser()
  166. ->description(__d('cake_console', "The Convert Shell converts files from dos/unix/mac to another system"))
  167. ->addSubcommand('version', array(
  168. 'help' => __d('cake_console', 'Test and display version.'),
  169. 'parser' => $subcommandParser
  170. ))
  171. ->addSubcommand('folder', array(
  172. 'help' => __d('cake_console', 'Convert folder recursivly (Tools.Convert folder [options] [path])'),
  173. 'parser' => $subcommandParser
  174. ));
  175. }
  176. }