ConvertShell.php 4.7 KB

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