From b8bbb17820be57eb7be248f00e49bfae283e27ef Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Thu, 25 Oct 2018 13:22:04 +0200 Subject: [PATCH] fix: handle undefined and null as stats value In certain cases depending on the inputFileSystem `stats` doesn't throw, but returns a falsey value such as `undefined` and `null`. In this case an error from globby will be thrown `Patterns must be a string or an array of strings` --- src/preProcessPattern.js | 18 +++++++++++++----- tests/index.js | 26 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/preProcessPattern.js b/src/preProcessPattern.js index ec7e286d..cf7048e6 100644 --- a/src/preProcessPattern.js +++ b/src/preProcessPattern.js @@ -59,21 +59,29 @@ export default function preProcessPattern(globalRef, pattern) { debug(`determined '${pattern.from}' to be read from '${pattern.absoluteFrom}'`); - return stat(inputFileSystem, pattern.absoluteFrom) - .catch(() => { + const noStatsHandler = () => { // If from doesn't appear to be a glob, then log a warning if (isGlob(pattern.from) || pattern.from.indexOf('*') !== -1) { pattern.fromType = 'glob'; pattern.glob = escape(pattern.context, pattern.from); } else { const msg = `unable to locate '${pattern.from}' at '${pattern.absoluteFrom}'`; - warning(msg); - compilation.errors.push(`[copy-webpack-plugin] ${msg}`); + const warningMsg = `[copy-webpack-plugin] ${msg}`; + // only display the same message once + if (compilation.errors.indexOf(warningMsg) === -1) { + warning(msg); + compilation.errors.push(warningMsg); + } + pattern.fromType = 'nonexistent'; } - }) + }; + + return stat(inputFileSystem, pattern.absoluteFrom) + .catch(() => noStatsHandler()) .then((stat) => { if (!stat) { + noStatsHandler(); return pattern; } diff --git a/tests/index.js b/tests/index.js index 071ead0f..5c272eca 100644 --- a/tests/index.js +++ b/tests/index.js @@ -56,6 +56,15 @@ class MockCompiler { } } + +class MockCompilerNoStat extends MockCompiler { + constructor (options = {}) { + super(options); + + this.inputFileSystem.stat = (file, cb) => cb(undefined, undefined); + } +} + describe('apply function', () => { // Ideally we pass in patterns and confirm the resulting assets const run = (opts) => { @@ -553,6 +562,23 @@ describe('apply function', () => { .catch(done); }); + it('warns when file not found and stats is undefined', (done) => { + runEmit({ + compiler: new MockCompilerNoStat(), + expectedAssetKeys: [], + expectedErrors: [ + `[copy-webpack-plugin] unable to locate 'nonexistent.txt' at '${HELPER_DIR}${path.sep}nonexistent.txt'` + ], + patterns: [{ + from: 'nonexistent.txt', + to: '.', + toType: 'dir' + }] + }) + .then(done) + .catch(done); + }); + it('warns when tranform failed', (done) => { runEmit({ expectedAssetKeys: [],