function run()

in src/Runner.js [162:316]


function run(transformFile, paths, options) {
  let usedRemoteScript = false;
  const cpus = options.cpus ? Math.min(availableCpus, options.cpus) : availableCpus;
  const extensions =
    options.extensions && options.extensions.split(',').map(ext => '.' + ext);
  const fileCounters = {error: 0, ok: 0, nochange: 0, skip: 0};
  const statsCounter = {};
  const startTime = process.hrtime();

  ignores.add(options.ignorePattern);
  ignores.addFromFile(options.ignoreConfig);

  if (/^http/.test(transformFile)) {
    usedRemoteScript = true;
    return new Promise((resolve, reject) => {
      // call the correct `http` or `https` implementation
      (transformFile.indexOf('https') !== 0 ?  http : https).get(transformFile, (res) => {
        let contents = '';
        res
          .on('data', (d) => {
            contents += d.toString();
          })
          .on('end', () => {
            const ext = path.extname(transformFile);
            temp.open({ prefix: 'jscodeshift', suffix: ext }, (err, info) => {
              if (err) return reject(err);
              fs.write(info.fd, contents, function (err) {
                if (err) return reject(err);
                fs.close(info.fd, function(err) {
                  if (err) return reject(err);
                  transform(info.path).then(resolve, reject);
                });
              });
            });
        })
      })
      .on('error', (e) => {
        reject(e);
      });
    });
  } else if (!fs.existsSync(transformFile)) {
    process.stderr.write(
      chalk.white.bgRed('ERROR') + ' Transform file ' + transformFile + ' does not exist \n'
    );
    return;
  } else {
    return transform(transformFile);
  }

  function transform(transformFile) {
    return getAllFiles(
      paths,
      name => !extensions || extensions.indexOf(path.extname(name)) != -1
    ).then(files => {
        const numFiles = files.length;

        if (numFiles === 0) {
          process.stdout.write('No files selected, nothing to do. \n');
          return [];
        }

        const processes = options.runInBand ? 1 : Math.min(numFiles, cpus);
        const chunkSize = processes > 1 ?
          Math.min(Math.ceil(numFiles / processes), CHUNK_SIZE) :
          numFiles;

        let index = 0;
        // return the next chunk of work for a free worker
        function next() {
          if (!options.silent && !options.runInBand && index < numFiles) {
            process.stdout.write(
              'Sending ' +
              Math.min(chunkSize, numFiles-index) +
              ' files to free worker...\n'
            );
          }
          return files.slice(index, index += chunkSize);
        }

        if (!options.silent) {
          process.stdout.write('Processing ' + files.length + ' files... \n');
          if (!options.runInBand) {
            process.stdout.write(
              'Spawning ' + processes +' workers...\n'
            );
          }
          if (options.dry) {
            process.stdout.write(
              chalk.green('Running in dry mode, no files will be written! \n')
            );
          }
        }

        const args = [transformFile, options.babel ? 'babel' : 'no-babel'];

        const workers = [];
        for (let i = 0; i < processes; i++) {
          workers.push(options.runInBand ?
            require('./Worker')(args) :
            child_process.fork(require.resolve('./Worker'), args)
          );
        }

        return workers.map(child => {
          child.send({files: next(), options});
          child.on('message', message => {
            switch (message.action) {
              case 'status':
                fileCounters[message.status] += 1;
                log[message.status](lineBreak(message.msg), options.verbose);
                break;
              case 'update':
                if (!statsCounter[message.name]) {
                  statsCounter[message.name] = 0;
                }
                statsCounter[message.name] += message.quantity;
                break;
              case 'free':
                child.send({files: next(), options});
                break;
              case 'report':
                report(message);
                break;
            }
          });
          return new Promise(resolve => child.on('disconnect', resolve));
        });
      })
      .then(pendingWorkers =>
        Promise.all(pendingWorkers).then(() => {
          const endTime = process.hrtime(startTime);
          const timeElapsed = (endTime[0] + endTime[1]/1e9).toFixed(3);
          if (!options.silent) {
            process.stdout.write('All done. \n');
            showFileStats(fileCounters);
            showStats(statsCounter);
            process.stdout.write(
              'Time elapsed: ' + timeElapsed + 'seconds \n'
            );
            
            if (options.failOnError && fileCounters.error > 0) {
              process.exit(1);
            }
          }
          if (usedRemoteScript) {
            temp.cleanupSync();
          }
          return Object.assign({
            stats: statsCounter,
            timeElapsed: timeElapsed
          }, fileCounters);
        })
      );
  }
}