mirror of https://github.com/webpack/webpack.git
fix: CleanPlugin unlink same file twice (#19595)
Github Actions / lint (push) Has been cancelled
Details
Github Actions / validate-legacy-node (push) Has been cancelled
Details
Github Actions / benchmark (1/4) (push) Has been cancelled
Details
Github Actions / benchmark (2/4) (push) Has been cancelled
Details
Github Actions / benchmark (3/4) (push) Has been cancelled
Details
Github Actions / benchmark (4/4) (push) Has been cancelled
Details
Github Actions / basic (push) Has been cancelled
Details
Github Actions / unit (push) Has been cancelled
Details
Github Actions / integration (10.x, macos-latest, a) (push) Has been cancelled
Details
Github Actions / integration (10.x, macos-latest, b) (push) Has been cancelled
Details
Github Actions / integration (10.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (10.x, ubuntu-latest, b) (push) Has been cancelled
Details
Github Actions / integration (10.x, windows-latest, a) (push) Has been cancelled
Details
Github Actions / integration (10.x, windows-latest, b) (push) Has been cancelled
Details
Github Actions / integration (12.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (14.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (16.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (18.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (20.x, macos-latest, a) (push) Has been cancelled
Details
Github Actions / integration (20.x, macos-latest, b) (push) Has been cancelled
Details
Github Actions / integration (20.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (20.x, ubuntu-latest, b) (push) Has been cancelled
Details
Github Actions / integration (20.x, windows-latest, a) (push) Has been cancelled
Details
Github Actions / integration (20.x, windows-latest, b) (push) Has been cancelled
Details
Github Actions / integration (22.x, macos-latest, a) (push) Has been cancelled
Details
Github Actions / integration (22.x, macos-latest, b) (push) Has been cancelled
Details
Github Actions / integration (22.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (22.x, ubuntu-latest, b) (push) Has been cancelled
Details
Github Actions / integration (22.x, windows-latest, a) (push) Has been cancelled
Details
Github Actions / integration (22.x, windows-latest, b) (push) Has been cancelled
Details
Github Actions / integration (24.x, macos-latest, a) (push) Has been cancelled
Details
Github Actions / integration (24.x, macos-latest, b) (push) Has been cancelled
Details
Github Actions / integration (24.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (24.x, ubuntu-latest, b) (push) Has been cancelled
Details
Github Actions / integration (24.x, windows-latest, a) (push) Has been cancelled
Details
Github Actions / integration (24.x, windows-latest, b) (push) Has been cancelled
Details
Github Actions / integration (lts/*, ubuntu-latest, a, 1) (push) Has been cancelled
Details
Github Actions / integration (lts/*, ubuntu-latest, b, 1) (push) Has been cancelled
Details
Github Actions / lint (push) Has been cancelled
Details
Github Actions / validate-legacy-node (push) Has been cancelled
Details
Github Actions / benchmark (1/4) (push) Has been cancelled
Details
Github Actions / benchmark (2/4) (push) Has been cancelled
Details
Github Actions / benchmark (3/4) (push) Has been cancelled
Details
Github Actions / benchmark (4/4) (push) Has been cancelled
Details
Github Actions / basic (push) Has been cancelled
Details
Github Actions / unit (push) Has been cancelled
Details
Github Actions / integration (10.x, macos-latest, a) (push) Has been cancelled
Details
Github Actions / integration (10.x, macos-latest, b) (push) Has been cancelled
Details
Github Actions / integration (10.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (10.x, ubuntu-latest, b) (push) Has been cancelled
Details
Github Actions / integration (10.x, windows-latest, a) (push) Has been cancelled
Details
Github Actions / integration (10.x, windows-latest, b) (push) Has been cancelled
Details
Github Actions / integration (12.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (14.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (16.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (18.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (20.x, macos-latest, a) (push) Has been cancelled
Details
Github Actions / integration (20.x, macos-latest, b) (push) Has been cancelled
Details
Github Actions / integration (20.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (20.x, ubuntu-latest, b) (push) Has been cancelled
Details
Github Actions / integration (20.x, windows-latest, a) (push) Has been cancelled
Details
Github Actions / integration (20.x, windows-latest, b) (push) Has been cancelled
Details
Github Actions / integration (22.x, macos-latest, a) (push) Has been cancelled
Details
Github Actions / integration (22.x, macos-latest, b) (push) Has been cancelled
Details
Github Actions / integration (22.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (22.x, ubuntu-latest, b) (push) Has been cancelled
Details
Github Actions / integration (22.x, windows-latest, a) (push) Has been cancelled
Details
Github Actions / integration (22.x, windows-latest, b) (push) Has been cancelled
Details
Github Actions / integration (24.x, macos-latest, a) (push) Has been cancelled
Details
Github Actions / integration (24.x, macos-latest, b) (push) Has been cancelled
Details
Github Actions / integration (24.x, ubuntu-latest, a) (push) Has been cancelled
Details
Github Actions / integration (24.x, ubuntu-latest, b) (push) Has been cancelled
Details
Github Actions / integration (24.x, windows-latest, a) (push) Has been cancelled
Details
Github Actions / integration (24.x, windows-latest, b) (push) Has been cancelled
Details
Github Actions / integration (lts/*, ubuntu-latest, a, 1) (push) Has been cancelled
Details
Github Actions / integration (lts/*, ubuntu-latest, b, 1) (push) Has been cancelled
Details
This commit is contained in:
parent
4df83e7c54
commit
93eb096c84
|
@ -6,6 +6,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const asyncLib = require("neo-async");
|
const asyncLib = require("neo-async");
|
||||||
|
const path = require("path");
|
||||||
const { SyncBailHook } = require("tapable");
|
const { SyncBailHook } = require("tapable");
|
||||||
const Compilation = require("./Compilation");
|
const Compilation = require("./Compilation");
|
||||||
const createSchemaValidation = require("./util/create-schema-validation");
|
const createSchemaValidation = require("./util/create-schema-validation");
|
||||||
|
@ -61,6 +62,62 @@ const mergeAssets = (as1, as2) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Map<string, number>} assets current assets
|
||||||
|
* @returns {Set<string>} Set of directory paths
|
||||||
|
*/
|
||||||
|
function getDirectories(assets) {
|
||||||
|
const directories = new Set();
|
||||||
|
/**
|
||||||
|
* @param {string} filename asset filename
|
||||||
|
*/
|
||||||
|
const addDirectory = filename => {
|
||||||
|
directories.add(path.dirname(filename));
|
||||||
|
};
|
||||||
|
|
||||||
|
// get directories of assets
|
||||||
|
for (const [asset] of assets) {
|
||||||
|
addDirectory(asset);
|
||||||
|
}
|
||||||
|
// and all parent directories
|
||||||
|
for (const directory of directories) {
|
||||||
|
addDirectory(directory);
|
||||||
|
}
|
||||||
|
return directories;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} a First directory path to compare
|
||||||
|
* @param {string} b Second directory path to compare
|
||||||
|
* @returns {boolean} True if both paths have the same parent directory
|
||||||
|
*/
|
||||||
|
function isEqualPath(a, b) {
|
||||||
|
return path.normalize(a) === path.normalize(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Map<string, number>|Set<string>} files Collection of files to check against
|
||||||
|
* @param {string} file File path to check
|
||||||
|
* @returns {boolean} True if the file or its parent exists in the collection
|
||||||
|
*/
|
||||||
|
function hasFile(files, file) {
|
||||||
|
if (files instanceof Set) {
|
||||||
|
for (const dir of files) {
|
||||||
|
if (isEqualPath(dir, file)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (files instanceof Map) {
|
||||||
|
for (const dir of files.keys()) {
|
||||||
|
if (isEqualPath(dir, file)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/** @typedef {Set<string>} Diff */
|
/** @typedef {Set<string>} Diff */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,15 +128,7 @@ const mergeAssets = (as1, as2) => {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
const getDiffToFs = (fs, outputPath, currentAssets, callback) => {
|
const getDiffToFs = (fs, outputPath, currentAssets, callback) => {
|
||||||
const directories = new Set();
|
const directories = getDirectories(currentAssets);
|
||||||
// get directories of assets
|
|
||||||
for (const [asset] of currentAssets) {
|
|
||||||
directories.add(asset.replace(/(^|\/)[^/]*$/, ""));
|
|
||||||
}
|
|
||||||
// and all parent directories
|
|
||||||
for (const directory of directories) {
|
|
||||||
directories.add(directory.replace(/(^|\/)[^/]*$/, ""));
|
|
||||||
}
|
|
||||||
const diff = new Set();
|
const diff = new Set();
|
||||||
asyncLib.forEachLimit(
|
asyncLib.forEachLimit(
|
||||||
directories,
|
directories,
|
||||||
|
@ -98,7 +147,10 @@ const getDiffToFs = (fs, outputPath, currentAssets, callback) => {
|
||||||
for (const entry of /** @type {string[]} */ (entries)) {
|
for (const entry of /** @type {string[]} */ (entries)) {
|
||||||
const file = entry;
|
const file = entry;
|
||||||
const filename = directory ? `${directory}/${file}` : file;
|
const filename = directory ? `${directory}/${file}` : file;
|
||||||
if (!directories.has(filename) && !currentAssets.has(filename)) {
|
if (
|
||||||
|
!hasFile(directories, filename) &&
|
||||||
|
!hasFile(currentAssets, filename)
|
||||||
|
) {
|
||||||
diff.add(filename);
|
diff.add(filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,3 +495,6 @@ class CleanPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = CleanPlugin;
|
module.exports = CleanPlugin;
|
||||||
|
module.exports._getDirectories = getDirectories;
|
||||||
|
module.exports._hasFile = hasFile;
|
||||||
|
module.exports._isEqualPath = isEqualPath;
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const {
|
||||||
|
_getDirectories,
|
||||||
|
_hasFile,
|
||||||
|
_isEqualPath
|
||||||
|
} = require("../lib/CleanPlugin");
|
||||||
|
|
||||||
|
describe("CleanPlugin", () => {
|
||||||
|
describe("_getDirectories", () => {
|
||||||
|
it("should return empty set when assets map is empty", () => {
|
||||||
|
const assets = new Map();
|
||||||
|
const result = _getDirectories(assets);
|
||||||
|
expect(result).toBeInstanceOf(Set);
|
||||||
|
expect(result.size).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should extract root directory from single file path", () => {
|
||||||
|
const assets = new Map([["./static.js", 0]]);
|
||||||
|
const result = _getDirectories(assets);
|
||||||
|
expect(Array.from(result)).toEqual(["."]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should extract all parent directories from deep nested path", () => {
|
||||||
|
const assets = new Map([["this/dir/should/not/be/removed/file.ext", 0]]);
|
||||||
|
const result = _getDirectories(assets);
|
||||||
|
expect(Array.from(result)).toEqual([
|
||||||
|
"this/dir/should/not/be/removed",
|
||||||
|
"this/dir/should/not/be",
|
||||||
|
"this/dir/should/not",
|
||||||
|
"this/dir/should",
|
||||||
|
"this/dir",
|
||||||
|
"this",
|
||||||
|
"."
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should extract root and first level directories", () => {
|
||||||
|
const assets = new Map([
|
||||||
|
["./main.js", 0],
|
||||||
|
["./js/main.js", 0]
|
||||||
|
]);
|
||||||
|
const result = _getDirectories(assets);
|
||||||
|
expect(Array.from(result)).toEqual([".", "./js"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should extract all nested directory levels", () => {
|
||||||
|
const assets = new Map([
|
||||||
|
["./main.js", 0],
|
||||||
|
["./js/main.js", 0],
|
||||||
|
["./static/js/main.js", 0]
|
||||||
|
]);
|
||||||
|
const result = _getDirectories(assets);
|
||||||
|
expect(Array.from(result)).toEqual([
|
||||||
|
".",
|
||||||
|
"./js",
|
||||||
|
"./static/js",
|
||||||
|
"./static"
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("_isEqualPath", () => {
|
||||||
|
it("should normalize paths before comparison", () => {
|
||||||
|
expect(_isEqualPath("this", "this")).toBe(true);
|
||||||
|
expect(_isEqualPath("this", "./this")).toBe(true);
|
||||||
|
expect(_isEqualPath("this/a", "./this/a")).toBe(true);
|
||||||
|
expect(_isEqualPath("this", "this/a")).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("_hasFile", () => {
|
||||||
|
it("should find file in Set collection", () => {
|
||||||
|
const files = new Set(["this"]);
|
||||||
|
expect(_hasFile(files, "./this")).toBe(true);
|
||||||
|
expect(_hasFile(files, "this")).toBe(true);
|
||||||
|
expect(_hasFile(files, "this/a")).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should find file in Map collection", () => {
|
||||||
|
const files = new Map([["this", 0]]);
|
||||||
|
expect(_hasFile(files, "this")).toBe(true);
|
||||||
|
expect(_hasFile(files, "./this")).toBe(true);
|
||||||
|
expect(_hasFile(files, "this/a")).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue