From 66b1e9526150e74ddd7e4190356facd783fb3b44 Mon Sep 17 00:00:00 2001 From: Clayton Ramsey Date: Thu, 6 Aug 2026 00:42:52 -0500 Subject: [PATCH] fix: support Cargo V2 build dir layout (#371) --- src/cleanup.ts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/cleanup.ts b/src/cleanup.ts index 4db4b80..07baa15 100644 --- a/src/cleanup.ts +++ b/src/cleanup.ts @@ -245,6 +245,12 @@ const ONE_WEEK = 7 * 24 * 3600 * 1000; * Otherwise, it will remove everything that does not match any string in the * `keepPrefix` set. * The matching strips and trailing `-$hash` suffix. + * + * Cargo's newer `build-dir` layout (rust-lang/cargo#17258) nests the hash as + * a subdirectory instead of appending it, so entries there are bare package + * names with no suffix to strip. Check for an exact match first so those + * names (which may themselves contain hyphens) aren't mistaken for a + * `-` entry from the old layout and truncated incorrectly. */ async function rmExcept(dirName: string, keepPrefix: Set, checkTimestamp = false) { const dir = await fs.promises.opendir(dirName); @@ -262,14 +268,21 @@ async function rmExcept(dirName: string, keepPrefix: Set, checkTimestamp let name = dirent.name; - // strip the trailing hash - const idx = name.lastIndexOf("-"); - if (idx !== -1) { - name = name.slice(0, idx); - } + // in Cargo's V1 layout, all packages are suffixed by their hash. + // in V2, all package hashes are subdirectories instead. + // Check both possible naming standards for packages and accept either. + // v2 package format if (!keepPrefix.has(name)) { - await rm(dir.path, dirent); + // now check for v1 package format + // strip the trailing hash + const idx = name.lastIndexOf("-"); + if (idx !== -1) { + name = name.slice(0, idx); + } + if (!keepPrefix.has(name)) { + await rm(dir.path, dirent); + } } } }