From 0c6f5e85311a5cedc26a588b9812eadca5ec942a Mon Sep 17 00:00:00 2001 From: Joachim Viide Date: Tue, 5 Mar 2024 11:39:39 +0200 Subject: [PATCH] fix(path): fix common() results that depend on the order and/or number of input paths (#4414) --- path/_common/common.ts | 18 +++++++++--------- path/common_test.ts | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/path/_common/common.ts b/path/_common/common.ts index f7336f1f2a5f..b6d327b04074 100644 --- a/path/_common/common.ts +++ b/path/_common/common.ts @@ -3,24 +3,24 @@ export function _common(paths: string[], sep: string): string { const [first = "", ...remaining] = paths; - if (first === "" || remaining.length === 0) { - return first.substring(0, first.lastIndexOf(sep) + 1); - } const parts = first.split(sep); let endOfPrefix = parts.length; + let append = ""; for (const path of remaining) { const compare = path.split(sep); + if (compare.length <= endOfPrefix) { + endOfPrefix = compare.length; + append = ""; + } + for (let i = 0; i < endOfPrefix; i++) { if (compare[i] !== parts[i]) { endOfPrefix = i; + append = i === 0 ? "" : sep; + break; } } - - if (endOfPrefix === 0) { - return ""; - } } - const prefix = parts.slice(0, endOfPrefix).join(sep); - return prefix.endsWith(sep) ? prefix : `${prefix}${sep}`; + return parts.slice(0, endOfPrefix).join(sep) + append; } diff --git a/path/common_test.ts b/path/common_test.ts index 3fc77533f480..e1e2f5ce32f1 100644 --- a/path/common_test.ts +++ b/path/common_test.ts @@ -42,3 +42,45 @@ Deno.test({ assertEquals(actual, "c:\\deno\\"); }, }); + +Deno.test({ + name: "common(['', '/'], '/') returns ''", + fn() { + const actual = common(["", "/"], "/"); + assertEquals(actual, ""); + }, +}); + +Deno.test({ + name: "common(['/', ''], '/') returns ''", + fn() { + const actual = common([ + "/", + "", + ], "/"); + assertEquals(actual, ""); + }, +}); + +Deno.test({ + name: "common() returns the first path unmodified when it's the only path", + fn() { + const actual = common(["./deno/std/path/mod.ts"], "/"); + assertEquals(actual, "./deno/std/path/mod.ts"); + }, +}); + +Deno.test({ + name: "common() returns the first path unmodified if all paths are equal", + fn() { + const actual = common( + [ + "./deno/std/path/mod.ts", + "./deno/std/path/mod.ts", + "./deno/std/path/mod.ts", + ], + "/", + ); + assertEquals(actual, "./deno/std/path/mod.ts"); + }, +});