ConvertShell.php 4.5 KB

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