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);
})
);
}
}