Skip to content

Commit 40159a2

Browse files
committed
fix: use isFileInFolder for cross-platform opaque whiteout dir matching
isFileInOpaqueDir was using path.dirname and path.sep directly, which breaks on Windows where path.sep is \ but Docker paths use /. Reuse the existing isFileInFolder helper which normalizes paths first — same pattern as isFileInARemovedFolder.
1 parent cb73d68 commit 40159a2

File tree

1 file changed

+14
-17
lines changed

1 file changed

+14
-17
lines changed

lib/extractor/index.ts

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,8 @@ function layersWithLatestFileModifications(
236236

237237
// TODO: This removes the information about the layer name, maybe we would need it in the future?
238238
for (const layer of layers) {
239-
// Collect opaque whiteout dirs from this layer, but don't apply them yet —
240-
// they should only affect older layers, not files in the same layer.
239+
// Collect opaque whiteout dirs from this layer, but don't apply yet —
240+
// they only affect older layers, not the current one.
241241
const layerOpaqueDirs: Set<string> = new Set();
242242

243243
// go over extracted files products found in this layer
@@ -270,7 +270,7 @@ function layersWithLatestFileModifications(
270270
}
271271
}
272272

273-
// Apply this layer's opaque whiteouts for subsequent (older) layers
273+
// Apply this layer's opaque whiteouts to older layers
274274
for (const dir of layerOpaqueDirs) {
275275
opaqueWhiteoutDirs.add(dir);
276276
}
@@ -279,8 +279,7 @@ function layersWithLatestFileModifications(
279279
}
280280

281281
/**
282-
* check if a file is 'whited out', which is shown by
283-
* prefixing the filename with a .wh.
282+
* check if a file is 'whited out' (filename starts with .wh.)
284283
* https://www.madebymikal.com/interpreting-whiteout-files-in-docker-image-layers
285284
* https://github.com/opencontainers/image-spec/blob/main/layer.md#whiteouts
286285
*/
@@ -298,33 +297,31 @@ export function isOpaqueWhiteout(filename: string): boolean {
298297
}
299298

300299
/**
301-
* Extract the basename from a path, handling both Unix and Windows separators
302-
* regardless of the current platform.
300+
* Extract the basename from a path, handling both / and \ separators cross-platform.
303301
*/
304302
function getBasename(filename: string): string {
305-
const lastSlash = Math.max(filename.lastIndexOf("/"), filename.lastIndexOf("\\"));
303+
const lastSlash = Math.max(
304+
filename.lastIndexOf("/"),
305+
filename.lastIndexOf("\\"),
306+
);
306307
return lastSlash === -1 ? filename : filename.substring(lastSlash + 1);
307308
}
308309

309310
function isFileInOpaqueDir(
310311
filename: string,
311312
opaqueWhiteoutDirs: Set<string>,
312313
): boolean {
313-
const dir = path.dirname(filename);
314-
for (const opaqueDir of opaqueWhiteoutDirs) {
315-
if (dir === opaqueDir || dir.startsWith(opaqueDir + path.sep)) {
316-
return true;
317-
}
318-
}
319-
return false;
314+
return Array.from(opaqueWhiteoutDirs).some((opaqueDir) =>
315+
isFileInFolder(filename, opaqueDir),
316+
);
320317
}
321318

322319
/**
323320
* Remove the .wh. prefix from a whiteout file to get the original filename
324321
*/
325322
export function removeWhiteoutPrefix(filename: string): string {
326-
// Replace .wh. that appears at the start or after the last slash/backslash,
327-
// and ensure no slashes/backends come after .wh.
323+
// Replace .wh. at the start or after the last slash/backslash.
324+
// Don't match if there are slashes after .wh.
328325
return filename.replace(/^(.*[\/\\])?\.wh\.([^\/\\]*)$/, "$1$2");
329326
}
330327

0 commit comments

Comments
 (0)