tools.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. 'use strict';
  2. let dirtyFiles,
  3. ignoreList;
  4. module.exports = {
  5. /**
  6. * Check if a task (including its optional target) is in the queue of tasks to be executed by Grunt.
  7. *
  8. * @param grunt {Object} The Grunt object.
  9. * @param task {String} The task name. May optionally include the target (e.g. 'task:target').
  10. * @returns {Boolean} "true" if the task is in the queue.
  11. */
  12. checkTaskInQueue( grunt, task ) {
  13. const cliTasks = grunt.cli.tasks;
  14. // Check if the task has been called directly.
  15. const isDirectCall = ( cliTasks.indexOf( task ) > -1 );
  16. // Check if this is a "default" call and that the task is inside "default".
  17. const isDefaultTask = ( cliTasks.indexOf( 'default' ) > -1 ) || !cliTasks.length;
  18. // Hacking Grunt hard.
  19. const isTaskInDefault = isDefaultTask && ( grunt.task._tasks.default.info.indexOf( '"' + task + '"' ) > -1 );
  20. return isDirectCall || isTaskInDefault;
  21. },
  22. /**
  23. * Configures a multi-task and defines targets that are queued to be run by Grunt.
  24. *
  25. * @param grunt {Object} The Grunt object.
  26. * @param options {Object} A list of options for the method. See the jscs and jshint tasks for example.
  27. */
  28. setupMultitaskConfig( grunt, options ) {
  29. const task = options.task;
  30. const taskConfig = {};
  31. const config = taskConfig[ task ] = {
  32. options: options.defaultOptions
  33. };
  34. // "all" is the default target to be used if others are not to be run.
  35. const all = options.targets.all;
  36. let isAll = true;
  37. delete options.targets.all;
  38. Object.getOwnPropertyNames( options.targets ).forEach( function( target ) {
  39. if ( this.checkTaskInQueue( grunt, task + ':' + target ) ) {
  40. config[ target ] = options.targets[ target ]();
  41. isAll = false;
  42. }
  43. }, this );
  44. if ( isAll ) {
  45. config.all = all();
  46. }
  47. // Append .gitignore entries to the ignore list.
  48. if ( options.addGitIgnore ) {
  49. let ignoreProp = task + '.options.' + options.addGitIgnore;
  50. let ignores = grunt.config.get( ignoreProp ) || [];
  51. ignores = ignores.concat( this.getGitIgnore( grunt ) );
  52. grunt.config.set( ignoreProp, ignores );
  53. }
  54. // Merge over configurations set in gruntfile.js.
  55. grunt.config.merge( taskConfig );
  56. },
  57. /**
  58. * Gets the list of ignores from `.gitignore`.
  59. *
  60. * @param grunt {Object} The Grunt object.
  61. * @returns {String[]} The list of ignores.
  62. */
  63. getGitIgnore( grunt ) {
  64. if ( !ignoreList ) {
  65. ignoreList = grunt.file.read( '.gitignore' );
  66. ignoreList = ignoreList
  67. // Remove comment lines.
  68. .replace( /^#.*$/gm, '' )
  69. // Transform into array.
  70. .split( /\n+/ )
  71. // Remove empty entries.
  72. .filter( function( path ) {
  73. return !!path;
  74. } );
  75. }
  76. return ignoreList;
  77. },
  78. /**
  79. * Gets the list of files that are supposed to be included in the next Git commit.
  80. *
  81. * @returns {String[]} A list of file paths.
  82. */
  83. getGitDirtyFiles() {
  84. // Cache it, so it is executed only once when running multiple tasks.
  85. if ( !dirtyFiles ) {
  86. dirtyFiles = this
  87. // Compare the state of index with HEAD.
  88. .shExec( 'git diff-index --name-only HEAD' )
  89. // Remove trailing /n to avoid an empty entry.
  90. .replace( /\s*$/, '' )
  91. // Transform into array.
  92. .split( '\n' );
  93. // If nothing is returned, the array will one one empty string only.
  94. if ( dirtyFiles.length == 1 && !dirtyFiles[ 0 ] ) {
  95. dirtyFiles = [];
  96. }
  97. }
  98. return dirtyFiles;
  99. },
  100. /**
  101. * Executes a shell command.
  102. *
  103. * @param command {String} The command to be executed.
  104. * @returns {String} The command output.
  105. */
  106. shExec( command ) {
  107. const sh = require( 'shelljs' );
  108. sh.config.silent = true;
  109. const ret = sh.exec( command );
  110. if ( ret.code ) {
  111. throw new Error(
  112. 'Error while executing `' + command + '`:\n\n' +
  113. ret.output
  114. );
  115. }
  116. return ret.output;
  117. }
  118. };