@function
@name installGrunt
@description
Install grunt as the task-runner

@param {Object} answers - Answer values from the setup questions
327673
function installGrunt(answers) {
  console.log(chalk.gray("Installing 'grunt-cli' globally..."));
  installPackage('grunt-cli', true, answers.sudo);

  console.log(chalk.gray("Installing 'grunt' locally..."));
  installPackage('grunt', false, answers.sudo, 'save-dev');
}
121802
function getPackageMetaFile(answers) {
    const packageFields = ['name', 'version', 'license', 'category'];
    const packageObject = merge(pick(packageFields, answers),
        { dependencies: { 'rung-cli': '1.0.0' } });

    return {
        filename: path.join(answers.name, 'package.json'),
        content: JSON.stringify(packageObject, null, 2)
    };
}
269003
function (err, files) {
      if (err) {
        grunt.fail.fatal(err);
      }
      files.forEach(function (file) {
        var pathName = path.join(workspacePath, file);
        if (fs.statSync(pathName).isDirectory()) {
          if (file === activeWebpackage && choices.length > 0) {
            choices.splice(0, 0, file);
          } else {
            choices.push(file);
          }
        }
      });

      // get list of webpackages to upload from config
      var uploadWebpackages = grunt.config.get('workspaceConfig.uploadWebpackages');
      var i = 0;

      if (uploadWebpackages && uploadWebpackages.length) {
        // create upload list from config
        grunt.log.writeln('Webpackages to upload:');
        for (i = 0; i < uploadWebpackages.length; i++) {
          if (choices.indexOf(uploadWebpackages[i]) >= 0) {
            webpackages.push(uploadWebpackages[i]);
            grunt.log.writeln((i + 1) + ') ' + uploadWebpackages[i]);
          }
        }
        startUploads();
      } else {
        // get user decision
        choices.push('CANCEL');
        grunt.log.writeln('Please select all webpackages to upload ' +
            'or to CANCEL: ');
        for (i = 0; i < choices.length; i++) {
          grunt.log.writeln((i + 1) + ') ' + choices[i]);
        }
        var options = {
          questions: [
            {
              name: 'selectedWebpackages',
              type: 'input',
              message: 'Answer:'
            }
          ]
        };

        inquirer.prompt(options.questions).then(webpackagesSelected);
      }
    }
1109222
function fakeTargetTask(prefix){
    return function(){

      if (this.args.length !== 1) {
        return grunt.log.fail('Just give the name of the ' + prefix + ' you want like :\ngrunt ' + prefix + ':bower');
      }

      var done = this.async();
      var spawn = require('child_process').spawn;
      spawn('./node_modules/.bin/gulp', [ prefix, '--branch='+this.args[0] ].concat(grunt.option.flags()), {
        cwd : './node_modules/angular-ui-publisher',
        stdio: 'inherit'
      }).on('close', done);
    };
  }
685651
function setupByLink() {
    console.warn("symlink doesn't resolve __dirname.");

    const srcTaskDir = path.join(__dirname, 'tasks');

    // detect target package
    const targets = [];
    const PACKAGES_DIR = path.join(__dirname, '..');
    fs.readdirSync(PACKAGES_DIR)
    .forEach((filePath) => {
        const absPath = path.join(PACKAGES_DIR, filePath);
        if (fs.statSync(absPath).isDirectory()) {
            if (/^cdp-/.test(filePath)) {
                // check project.config.js
                try {
                    const config = require(path.join(absPath, 'project.config'));
                    if (config.required_tasks) {
                        targets.push({
                            path: absPath,
                            required_tasks: config.required_tasks,
                            task_dir: config.dir.task,
                        });
                    }
                } catch (error) {
                    return; // next
                }
            }
        }
    });

    // link
    targets.forEach((target) => {
        const dstTaskDir = path.join(target.path, target.task_dir);
        if (!fs.existsSync(dstTaskDir)) {
            // create tasks dir
            fs.mkdirSync(dstTaskDir);
        }

        target.required_tasks.forEach((task) => {
            const src = path.join(srcTaskDir, task);
            const dst = path.join(dstTaskDir, task);
            if (!fs.existsSync(src)) {
                console.error('task not found: ' + task);
                process.exit(1);
            }
            if (fs.existsSync(dst)) {
                fs.unlinkSync(dst);
            }
            fs.symlinkSync(src, dst, 'file');
        });
    });
}
527833
function mainTask() {
        options = this.options(defaultOptions);
        var target = this.target;

        this.files.forEach(function (file) {

            var destJson = app.path.join(file.dest, target + '.cssstats.json');
            var destHtml = app.path.join(file.dest, target + '.cssstats.html');

            var css = {
                concat: ''
            };

            css.concat = file.src.filter(function (filepath) {
                // Remove nonexistent files (it's up to you to filter or warn here).
                if (!grunt.file.exists(filepath)) {
                    grunt.log.warn('Source file "' + filepath + '" not found.');
                    return false;
                } else {
                    return true;
                }
            }).map(function (filepath) {
                // Read and return the file's source.

                css[filepath] = app.fs.readFileSync(filepath, 'utf8');

                return '/****\n    source: ' + filepath + '\n****/\n\n' + css[filepath];

            }).join('\n');

            var stats = parseStats(css);

            if (options.logConsole) {
                console.log(stats);
            }

            if (options.jsonOutput) {
                var statsString = JSON.stringify(stats, undefined, 4);
                grunt.file.write(destJson, statsString);
            }

            if (options.htmlOutput) {
                var output = app.parseHtml(app, options, stats, css);
                grunt.file.write(destHtml, output);
            }
        });

    }
1165448
function proceedConcatTask(task, done) {
      var sources          = task.src;
      var dest             = task.dest;
      var options          = task.options;
      var lazy             = options.lazy;
      var transformsConcat = options.transformsConcat.slice(0);
      var separator        = options.separator;
      var banner           = options.banner;
      var footer           = options.footer;
      var mode             = options.mode;
      var statSources      = {};
      var statDest;

      grunt.verbose.writeln('Concat [%s] -> %s', sources.join(',').blue, dest.blue);

      async.series([
        // All sources stats
        function(next) {
          Q.all(sources.map(function(src) {
            return Q.nfcall(fs.stat, src)
            .then(function(stat) {
              statSources[src] = stat;
            });
          }))
          .then(function() { next(); })
          .fail(function(err) {next(err);});
        },

        // Destination stats
        function(next) {
          fs.stat(dest, function(err, stat) {
            // Ignore error
            statDest = stat;
            next();
          });
        },

        // Lazy mode
        function(next) {
          // If not lazy or if destination do not exist, continue
          if(!lazy || !statDest) {
            return next();
          }

          // If any of the sources is newer than dest, then continue,
          // else, done in lazy mode
          if(_.any(statSources, function(statSrc) { return statSrc.mtime.getTime() > statDest.mtime.getTime();})) {
            next();
          } else {
            grunt.verbose.writeln('  Ignore :'+' Destination file (%s) is allready transformed (See options.lazy).'.grey, dest.blue);
            return done(null, false);
          }

        },

        // Make parent directory
        function(next) {
          // Here destination is allways a file.
          // Only the parent folder is required
          var dir = dirname(dest);
          if(dirExists[dir]) {
            return next();
          }

          grunt.verbose.writeln('  Make directory %s', dir.blue);
          mkdirp(dir, function(err) {
            if(err) {
              return next(err);
            }
            tally.dirs++;
            dirExists[dir] = true;
            return next();
          });

        },

        // Concat
        function(next) {
          var wait = 0;
          function _exec() {
            if(writtingFiles[dest]) {
              // Try leater
              grunt.verbose.writeln('  ... wait for %s before writing (%s)', dest, wait++);
              return setImmediate(_exec);
            }
            writtingFiles[dest] = true;

            var trans = [], transStream = through2();
            tally.concats++;

            // Each transform builder is called and combined in
            // one readable/writable stream using stream-combiner
            if(transformsConcat && transformsConcat.length) {
              trans = _(transformsConcat)
              // Call each tranform stream builder
              .map(function(f) {
                return f(sources, dest, _.extend({}, options));
              })
              // Keep only stream (ignore anything without a pipe() method)
              .filter(function(s) { return s && s.pipe; });
              transStream = bun(trans);
            }

            var mainStream    = new StreamStream({separator: ''});
            var bodyStream    = new StreamStream({separator: separator});
            var writeStream   = fs.createWriteStream(dest, {mode: mode});

            // Concat each sources
            sources.forEach(function(src) {
              if(!statSources[src].size) {
                return;
              }
              bodyStream.write(fs.createReadStream(src));
            });
            bodyStream.end();


            grunt.verbose.writeln(
              '  read([%s]) -> transform(count:%s) -> write(%s)',
              sources.join(',').blue,
              trans.length.toString().blue,
              dest.blue
            );

            // Pipe all together
            if(banner) {
              mainStream.write(strToStream(banner));
            }

            mainStream.write(bun([bodyStream, transStream]));

            if(footer) {
              mainStream.write(strToStream(footer));
            }

            mainStream.end();

            // Write out
            mainStream.pipe(writeStream);

            mainStream.on('error', function(error) {
              grunt.fail.fatal(error);
            });

            writeStream.once('finish', function() {
              writtingFiles[dest] = false;
              next();
            });
          }
          _exec();
        }
      ], function(err, result) {
        if(err) {
          grunt.log.error(err);
          grunt.log.writeln("Consider using a 'clean' task before running this task again");
          done(err);
        } else {
          // Finished with changes
          done(null, true);
        }
      });
    }
886470
function(callback) {
      if(typeof method !== 'undefined') {
        method = service.getMethod(method);
        CommonUtil.header(grunt, 'Method: ' + method.name);
        callback();
      } else {
        CommonUtil.header(grunt, '');
        RunUtil.promptMethod(service, function(err, m) {
          method = m;
          callback();
        });
      }
    }
945421
function build(TaskConfig, crx) {
    return new Promise(function(resolve, reject){
	mkdir(path.dirname(TaskConfig.dest), function(err){
	  if (err) {
	    return reject(err);
	  }

	  resolve();
	});
      })
      .then(function(){
	return crx.load(TaskConfig.src);
      })
      .then(function(){
	return crx.loadContents();
      })
      .then(function(archiveBuffer){
	if (path.extname(TaskConfig.dest) === '.zip') {
	  grunt.file.write(TaskConfig.dest, archiveBuffer);
	  grunt.log.ok(TaskConfig.dest + ' has been created.');
	}

	return archiveBuffer;
      })
      .then(function writeCrxArchive(archiveBuffer){
	if (path.extname(TaskConfig.dest) === '.crx') {
	  return crx.pack(archiveBuffer).then(function(crxBuffer) {
	    grunt.file.write(TaskConfig.dest, crxBuffer);
	    grunt.log.ok(TaskConfig.dest + ' has been created.');
	  }).catch(grunt.log.error);
	}
      });
  }
798532
function(callback) {

				// build a list of individual files
				var rasterFiles =	[];
				task.files.forEach(function(file) {
					if (!grunt.file.isDir(file.src[0]) && path.extname(file.dest).toLowerCase() !== '.svg') {
						rasterFiles.push(file.src[0]);
					}
				});

				// if there’s anything to optimize…
				if (rasterFiles.length > 0) {

					// get absolute paths to the stuff we’re optimizing
					var rasterFilesResolved = rasterFiles.map(function(dir) {
						return path.resolve(__dirname, '../' + dir);
					});

					// optimize as many times as the user wants
					async.timesSeries(options.optimize.input.picopt, function(i, next) {

						// let the user know that we’re optimizing inputs
						grunt.log.writeln('Optimizing inputs with picopt (pass ' + (i + 1) + ' of ' + options.optimize.input.picopt + ')…');

						// do the optimizations (with promises)
						optimizePicopt(rasterFilesResolved, binPath.picopt).then(function() {
							next();
						});

					}, callback);

				} else {
					callback(null);
				}

			}
162520
function () {
            count++;

            // all modules have been added have been added.
            if (count === modules.length) {
                // check if solution file content needs to be updated.
                if (isDirty) {
                    writeSolutionFileContents();
                    return;
                }

                // slight delay to ensure future tasks can interact with module files.
                setTimeout(done, 500);
                return;
            }

            var moduleName = modules[count];
            
            // ignore directory when module doesn't contain .csproj file.
            if (!fs.existsSync(path.join(options.modules, moduleName, moduleName + '.csproj'))) {
                addNextModule();
                return;
            }

            helpers.getProjectGuid(path.join(options.modules, moduleName, moduleName + '.csproj'), function (moduleGuid) {
                // module already exists in the solution, move onto the next one.
                if (alreadyInSolution(moduleGuid)) {
                    addNextModule();
                    return;
                }

                var projectReference = '\r\nProject("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "' + moduleName + '", "Orchard.Web\\Modules\\' + moduleName + '\\' + moduleName + '.csproj", "' + moduleGuid + '"\r\nEndProject\r\n';
                var projectConfiguationPlatforms = '\t\t' + moduleGuid + '.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t' + moduleGuid + '.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t' + moduleGuid + '.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t' + moduleGuid + '.Release|Any CPU.Build.0 = Release|Any CPU\r\n';

                solutionFileContents = _s.insert(solutionFileContents, solutionFileContents.lastIndexOf('EndProject') + 10, projectReference)
                
                var sectionStart = solutionFileContents.indexOf("GlobalSection(ProjectConfigurationPlatforms)");
                var sectionEnd = sectionStart + solutionFileContents.substring(sectionStart).indexOf('EndGlobalSection');

                solutionFileContents = _s.insert(solutionFileContents, sectionEnd, projectConfiguationPlatforms);

                sectionStart = solutionFileContents.indexOf("GlobalSection(NestedProjects)");
                sectionEnd = sectionStart + solutionFileContents.substring(sectionStart).indexOf('EndGlobalSection');
                solutionFileContents = _s.insert(solutionFileContents, sectionEnd, '\t' + moduleGuid + ' = {' + SOLUTION_DIRECTORY_MODULES + '}\r\n\t');

                isDirty = true;

                addNextModule();
            });
        }
1242070
function gruntPrepareRelease () {

        var bower = grunt.file.readJSON('bower.json');
        var version = bower.version;

        if (version !== grunt.config('pkg.version')) {
            throw new Error('Version mismatch in bower.json');
        }

        function searchForExistingTag () {
            return exec('git tag -l \"' + version + '\"');
        }

        function setGruntConfig (searchResult) {

            if ('' !== searchResult.stdout.trim()) {
                throw new Error('Tag \'' + version + '\' already exists');
            }

            grunt.config('buildTag', '');
            grunt.config('buildDir', releaseDirName);

        }

        var done = this.async();

        ensureCleanMaster()
            .then(searchForExistingTag)
            .then(setGruntConfig)
            .then(function () {
                done();
            })
            .catch(handleAsyncError.bind(undefined, done))
            .done();

    }
885408
function gruntYakTask(grunt) {
    'use strict';

    /**
     * @type {!Array<string>}
     */
    let filesToUpload = [];

    /**
     * @type {RequestSender}
     */
    let requestSender;

    /**
     * Register task for grunt.
     */
    grunt.registerMultiTask('yakjs', 'A grunt task to update the YAKjs via rest API.', function task() {
        /**
         * This tasks sends several http request asynchronous.
         * So let's get the done callback from the task runner.
         */
        let done = this.async();

        /**
         * @type {!TaskOptions}
         */
        let options = this.options(new TaskOptions());

        filesToUpload = [];

        this.files.forEach(file => {
            filesToUpload = filesToUpload.concat(file.src);
        });

        let logger = {
            log: grunt.log.writeln,
            error: grunt.log.error
        };

        uploadFiles(filesToUpload, options, logger)
            .then(() => {
                grunt.log.writeln('');
                grunt.log.ok('All files uploaded.');
            })
            .then(() => {
                return clearModuleCache(options, logger);
            })
            .then(() => {
                return startInstances(options, logger);
            })
            .then(done)
            .catch((message, error) => {
                grunt.log.writeln('');
                grunt.log.error(JSON.stringify(message, null, 4));
                grunt.fatal('One or more files could not be uploaded.');
                done();
            });
    });
}
370249
function(required, done) {
        if (arguments.length < 1 || required) {
          grunt.log.writeln('\nnpm install...');
          // Run npm install in project's directory
          grunt.util.spawn({cmd: 'npm', args: ['install'],
                            opts: {cwd: init.destpath, stdio: 'inherit'}},
              function(error, result, code) {
                if (done) {
                  done();
                }
              });
        } else if (done) {
          done();
        }
      }
1056436
function generateGruntfile (generatedConfig) {
  return function(grunt) {
    var path = require('path'),
        fs = require('fs');

    require('load-grunt-tasks')(grunt);

    grunt.initConfig(generatedConfig);

    grunt.registerTask('default', ['watch']);

    // Handle new files with that have a new, supported preprocessor
    grunt.event.on('watch', function(action, filepath) {
      var ext = path.extname(filepath);

      // Ignore directories
      if (fs.lstatSync(filepath).isDirectory()) return;

      if (action === 'added') {
        // This is a special message that's parsed by YA
        // to determine if support for an additional preprocessor is necessary
        // Note: this allows us to avoid controlling grunt manually within YA
        console.log('EXTADDED:' + ext);

      // Note: we don't do anything for newly added .js files
      // A new js file can't be the root unless it's changed to require
      // the current root and saved/changed
      } else if (action === 'changed' || action === 'deleted') {
        if (ext === '.js') {
          // Ignore bundles
          if (/.+bundle.js/g.test(filepath)) return;

          // Notify YA to recompute the roots and
          // generate a configuration
          console.log('JSCHANGED:' + filepath);
        }
      }
    });

    // For watching entire directories but allowing
    // the grunt.event binding to take care of it
    grunt.registerTask('noop', function () {});
  };
}
851182
function createBoilerplateFolder(answers) {
    return createFolder(answers.name)
        .tap(createFolder(`${answers.name}/info`))
        .catch(~reject(new Error(`Unable to create folder ${answers.name}`)))
        .return(answers);
}
810598
function npmInstall(path, success){

      var deferred = Q.defer();

      // 'success' is a flag passed from the perform cmd function which states whether the function ran
      if(success === false){
        deferred.resolve(success);
        return deferred.promise;
      }

      var hasPackage = grunt.file.isFile(path+'/package.json');

      if(options.npmInstall === true && hasPackage){

        var msg = '---> Install npm dependencies ==> '+path;
        var execString = 'cd '+path+' && npm install';

        grunt.log.writeln(msg);

        var child = exec(execString);

        // add events for logging
        child.stdout.on('data', function(data) {
          grunt.log.writeln(data);
        });
        child.stderr.on('data', function(data) {
          grunt.verbose.writeln(data);
        });
        child.on('close', function(code) {
          deferred.resolve(success);
        });

      }else{

        if(options.npmInstall === true) {
          var msg = '---> Skipping npm install as no package JSON was detected ==> ' + path;
          grunt.log.writeln(msg);
        }

        deferred.resolve();
      }


      return deferred.promise;

    }