diff --git a/src/mvnw.js b/src/mvnw.js index 15fbc010..936e66cf 100644 --- a/src/mvnw.js +++ b/src/mvnw.js @@ -7,7 +7,7 @@ const path = require('path'); const fs = require('fs'); const rel = require('relative'); const readline = require('readline'); -const {spawn} = require('child_process'); +const { spawn } = require('child_process'); const colors = require('colors'); /** @@ -30,7 +30,7 @@ let beginning, * @param {Object} opts - Opts provided to the "eoc" * @return {Array} of Maven options */ -module.exports.flags = function(opts) { +module.exports.flags = function (opts) { const sources = path.resolve(opts.sources); console.debug('Sources in %s', rel(sources)); const target = path.resolve(opts.target); @@ -58,7 +58,7 @@ module.exports.flags = function(opts) { * @param {Boolean} [batch] - Is it batch mode (TRUE) or interactive (FALSE)? * @return {Promise} of maven execution task */ -module.exports.mvnw = function(args, tgt, batch) { +module.exports.mvnw = function (args, tgt, batch) { return new Promise((resolve, reject) => { target = tgt; phase = args[0]; @@ -71,7 +71,7 @@ module.exports.mvnw = function(args, tgt, batch) { '--fail-fast', '--strict-checksums', ]), - cmd = `${bin } ${ params.join(' ')}`; + cmd = `${bin} ${params.join(' ')}`; console.debug('+ %s', cmd); const result = spawn( bin, @@ -114,7 +114,7 @@ module.exports.mvnw = function(args, tgt, batch) { function start() { running = true; beginning = Date.now(); - const check = function() { + const check = function () { if (running) { print(); setTimeout(check, 1000); @@ -143,14 +143,31 @@ function print() { * @return {Integer} Total number files. */ function count(dir, curr) { - if (fs.existsSync(dir)) { - for (const f of fs.readdirSync(dir)) { - const next = path.join(dir, f); - if (fs.statSync(next).isDirectory()) { + if (!fs.existsSync(dir)) { + return curr; + } + let files; + try { + files = fs.readdirSync(dir); + } catch (err) { + if (err.code === 'ENOENT') { + return curr; + } + throw err; + } + for (const f of files) { + const next = path.join(dir, f); + try { + const stats = fs.statSync(next); + if (stats.isDirectory()) { curr = count(next, curr); } else { curr++; } + } catch (err) { + if (err.code !== 'ENOENT') { + throw err; + } } } return curr; diff --git a/test/test_mvnw.js b/test/test_mvnw.js index 63b918c5..74e53d92 100644 --- a/test/test_mvnw.js +++ b/test/test_mvnw.js @@ -3,12 +3,15 @@ * SPDX-License-Identifier: MIT */ -const {mvnw, flags} = require('../src/mvnw'); +const { mvnw, flags } = require('../src/mvnw'); const assert = require('assert'); +const fs = require('fs'); +const path = require('path'); +const os = require('os'); describe('mvnw', () => { it('prints Maven own version', (done) => { - const opts = {batch: true}; + const opts = { batch: true }; mvnw(['--version', '--quiet'], null, opts.batch); done(); }); @@ -25,4 +28,24 @@ describe('mvnw', () => { done(); }); }); + it('handles race condition when files are deleted during counting', (done) => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'eoc-test-')); + const sub = path.join(dir, 'subdir'); + fs.mkdirSync(sub); + fs.writeFileSync(path.join(dir, 'file1.txt'), 'test'); + fs.writeFileSync(path.join(sub, 'file2.txt'), 'test'); + const opt = { + sources: 'sources', + target: dir, + parser: 'parser', + homeTag: 'homeTag' + }; + mvnw(['--version', '--quiet', ...flags(opt)]).then(() => { + fs.rmSync(dir, { recursive: true, force: true }); + done(); + }).catch((err) => { + fs.rmSync(dir, { recursive: true, force: true }); + done(err); + }); + }); });