From 574eff522c25281b4d6bde8e290a35cac0ffcdf0 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 6 May 2026 23:58:13 -0600 Subject: [PATCH] fix(maybeInstallable): match TERMS_EXTS_NON_BUILD against filename, not URL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `maybeInstallable` was checking `build.download.endsWith(ext)` for each extension in `TERMS_EXTS_NON_BUILD`. That list includes `.1` (intended for matching man-page section-1 files like `mytool.1`). Some packages publish via GitHub source-archive URLs of the form `https://api.github.com/repos/{owner}/{repo}/tarball/v1.0.1`. That URL ends in `.1` (the version's patch number), so the check incorrectly rejects the package's tarball as "not installable" — and silently, because `_classify` returns `null` and `transformAndUpdate`'s "ignore known, non-package extensions" comment hides the drop in the noise. Concrete impact: any package whose version ends in `.1` and whose download URL is a GitHub source-archive endpoint gets its newest release dropped. Observed for serviceman v1.0.1 (and v1.0.x patch releases generally), aliasman, vim plugins, etc. Fix: check `build.name` (the canonical filename) instead of `build.download`. The filename for `serviceman-v1.0.1.tar.gz` doesn't end in `.1` — it ends in `.tar.gz`. Real `.1` man-page files have `.1` in their `name` too, so detection of those is unaffected. --- triplet.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/triplet.js b/triplet.js index 66eae3f..933314d 100644 --- a/triplet.js +++ b/triplet.js @@ -456,14 +456,21 @@ var Triplet = ('object' === typeof module && exports) || {}; } } + // Check the filename, not the full URL. Some download URLs are API + // endpoints whose path tail looks like an extension match — e.g. + // `.../tarball/v1.0.1` ends with `.1` (a TERMS_EXTS_NON_BUILD entry + // intended for `manpage.1`), causing maybeInstallable to falsely + // reject any package version ending in `.1`. The filename itself is + // the canonical source for extension classification. + let filename = build.name || build.download; for (let ext of Triplet.TERMS_EXTS_NON_BUILD) { - if (build.download.endsWith(ext)) { + if (filename.endsWith(ext)) { return false; } } for (let re of Triplet._RE_TERMS_NON_BUILD) { - if (re.test(build.download)) { + if (re.test(filename)) { return false; } }