index.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. 'use strict';
  2. var fs = require('fs');
  3. var path = require('path');
  4. var log = require('gulplog');
  5. var yargs = require('yargs');
  6. var Liftoff = require('liftoff');
  7. var interpret = require('interpret');
  8. var v8flags = require('v8flags');
  9. var findRange = require('semver-greatest-satisfied-range');
  10. var ansi = require('./lib/shared/ansi');
  11. var exit = require('./lib/shared/exit');
  12. var tildify = require('./lib/shared/tildify');
  13. var makeTitle = require('./lib/shared/make-title');
  14. var cliOptions = require('./lib/shared/cli-options');
  15. var completion = require('./lib/shared/completion');
  16. var verifyDeps = require('./lib/shared/verify-dependencies');
  17. var cliVersion = require('./package.json').version;
  18. var getBlacklist = require('./lib/shared/get-blacklist');
  19. var toConsole = require('./lib/shared/log/to-console');
  20. var loadConfigFiles = require('./lib/shared/config/load-files');
  21. var mergeConfigToCliFlags = require('./lib/shared/config/cli-flags');
  22. var mergeConfigToEnvFlags = require('./lib/shared/config/env-flags');
  23. // Logging functions
  24. var logVerify = require('./lib/shared/log/verify');
  25. var logBlacklistError = require('./lib/shared/log/blacklist-error');
  26. // Get supported ranges
  27. var ranges = fs.readdirSync(path.join(__dirname, '/lib/versioned/'));
  28. // Set env var for ORIGINAL cwd
  29. // before anything touches it
  30. process.env.INIT_CWD = process.cwd();
  31. var cli = new Liftoff({
  32. name: 'gulp',
  33. processTitle: makeTitle('gulp', process.argv.slice(2)),
  34. completions: completion,
  35. extensions: interpret.jsVariants,
  36. v8flags: v8flags,
  37. configFiles: {
  38. '.gulp': {
  39. home: {
  40. path: '~',
  41. extensions: interpret.extensions,
  42. },
  43. cwd: {
  44. path: '.',
  45. extensions: interpret.extensions,
  46. },
  47. },
  48. },
  49. });
  50. var usage =
  51. '\n' + ansi.bold('Usage:') +
  52. ' gulp ' + ansi.blue('[options]') + ' tasks';
  53. var parser = yargs.usage(usage, cliOptions);
  54. var opts = parser.argv;
  55. cli.on('require', function(name) {
  56. // This is needed because interpret needs to stub the .mjs extension
  57. // Without the .mjs require hook, rechoir blows up
  58. // However, we don't want to show the mjs-stub loader in the logs
  59. if (path.basename(name, '.js') !== 'mjs-stub') {
  60. log.info('Requiring external module', ansi.magenta(name));
  61. }
  62. });
  63. cli.on('requireFail', function(name, error) {
  64. log.warn(
  65. ansi.yellow('Failed to load external module'),
  66. ansi.magenta(name)
  67. );
  68. /* istanbul ignore else */
  69. if (error) {
  70. log.warn(ansi.yellow(error.toString()));
  71. }
  72. });
  73. cli.on('respawn', function(flags, child) {
  74. var nodeFlags = ansi.magenta(flags.join(', '));
  75. var pid = ansi.magenta(child.pid);
  76. log.info('Node flags detected:', nodeFlags);
  77. log.info('Respawned to PID:', pid);
  78. });
  79. function run() {
  80. cli.prepare({
  81. cwd: opts.cwd,
  82. configPath: opts.gulpfile,
  83. require: opts.require,
  84. completion: opts.completion,
  85. }, function(env) {
  86. var cfgLoadOrder = ['home', 'cwd'];
  87. var cfg = loadConfigFiles(env.configFiles['.gulp'], cfgLoadOrder);
  88. opts = mergeConfigToCliFlags(opts, cfg);
  89. env = mergeConfigToEnvFlags(env, cfg, opts);
  90. env.configProps = cfg;
  91. // Set up event listeners for logging again after configuring.
  92. toConsole(log, opts);
  93. cli.execute(env, env.nodeFlags, handleArguments);
  94. });
  95. }
  96. module.exports = run;
  97. // The actual logic
  98. function handleArguments(env) {
  99. // This translates the --continue flag in gulp
  100. // To the settle env variable for undertaker
  101. // We use the process.env so the user's gulpfile
  102. // Can know about the flag
  103. if (opts.continue) {
  104. process.env.UNDERTAKER_SETTLE = 'true';
  105. }
  106. if (opts.help) {
  107. parser.showHelp(console.log);
  108. exit(0);
  109. }
  110. // Anything that needs to print outside of the logging mechanism should use console.log
  111. if (opts.version) {
  112. console.log('CLI version:', cliVersion);
  113. console.log('Local version:', env.modulePackage.version || 'Unknown');
  114. exit(0);
  115. }
  116. if (opts.verify) {
  117. var pkgPath = opts.verify !== true ? opts.verify : 'package.json';
  118. /* istanbul ignore else */
  119. if (path.resolve(pkgPath) !== path.normalize(pkgPath)) {
  120. pkgPath = path.join(env.cwd, pkgPath);
  121. }
  122. log.info('Verifying plugins in ' + pkgPath);
  123. return getBlacklist(function(err, blacklist) {
  124. /* istanbul ignore if */
  125. if (err) {
  126. return logBlacklistError(err);
  127. }
  128. var blacklisted = verifyDeps(require(pkgPath), blacklist);
  129. logVerify(blacklisted);
  130. });
  131. }
  132. if (!env.modulePath) {
  133. /* istanbul ignore next */
  134. var missingNodeModules =
  135. fs.existsSync(path.join(env.cwd, 'package.json'))
  136. && !fs.existsSync(path.join(env.cwd, 'node_modules'));
  137. /* istanbul ignore next */
  138. var missingGulpMessage =
  139. missingNodeModules
  140. ? 'Local modules not found in'
  141. : 'Local gulp not found in';
  142. log.error(
  143. ansi.red(missingGulpMessage),
  144. ansi.magenta(tildify(env.cwd))
  145. );
  146. var hasYarn = fs.existsSync(path.join(env.cwd, 'yarn.lock'));
  147. /* istanbul ignore next */
  148. var installCommand =
  149. missingNodeModules
  150. ? hasYarn
  151. ? 'yarn install'
  152. : 'npm install'
  153. : hasYarn
  154. ? 'yarn add gulp'
  155. : 'npm install gulp';
  156. log.error(ansi.red('Try running: ' + installCommand));
  157. exit(1);
  158. }
  159. if (!env.configPath) {
  160. log.error(ansi.red('No gulpfile found'));
  161. exit(1);
  162. }
  163. // Chdir before requiring gulpfile to make sure
  164. // we let them chdir as needed
  165. if (process.cwd() !== env.cwd) {
  166. process.chdir(env.cwd);
  167. log.info(
  168. 'Working directory changed to',
  169. ansi.magenta(tildify(env.cwd))
  170. );
  171. }
  172. // Find the correct CLI version to run
  173. var range = findRange(env.modulePackage.version, ranges);
  174. if (!range) {
  175. log.error(
  176. ansi.red('Unsupported gulp version', env.modulePackage.version)
  177. );
  178. exit(1);
  179. }
  180. // Load and execute the CLI version
  181. var versionedDir = path.join(__dirname, '/lib/versioned/', range, '/');
  182. require(versionedDir)(opts, env, env.configProps);
  183. }