-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: improve heuristics when dist-tags.latest is in range #33
feat: improve heuristics when dist-tags.latest is in range #33
Conversation
rebased onto main (can't force push, no longer have access to this repo) From 0637cf6083d8038494ddd4d2cbf57bef4f5dac4c Mon Sep 17 00:00:00 2001
From: isaacs <i@izs.me>
Date: Wed, 28 Jul 2021 12:34:15 -0700
Subject: [PATCH] fix: improve heuristics when dist-tags.latest is in range
Previously, there were two problems.
First problem, even though we heuristically choose the version that best
suits the stated 'engines' restriction, we were skipping that check when
the 'defaultTag' (ie, 'latest', typically) version was a semver match.
Second problem, the heuristic was improperly being set for 'staged' and
'restricted' packages, resulting in failure to sort those versions
properly.
Only choose the defaultTag version if it both a semver match, _and_
passes the engines/staged/restricted heuristics, and apply those
heuristics properly in the sort that comes later, if the defaultTag
version is not used.
Related-to: https://github.com/npm/rfcs/pull/405
---
lib/index.js | 16 +++++++++++-----
test/index.js | 13 ++++++++++++-
2 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/lib/index.js b/lib/index.js
index 42e41b1..8280797 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -123,9 +123,15 @@ const pickManifest = (packument, wanted, opts) => {
const defaultVer = distTags[defaultTag]
if (defaultVer &&
(range === '*' || semver.satisfies(defaultVer, range, { loose: true })) &&
+ !restricted[defaultVer] &&
!shouldAvoid(defaultVer, avoid)) {
const mani = versions[defaultVer]
- if (mani && isBefore(verTimes, defaultVer, time)) {
+ const ok = mani &&
+ isBefore(verTimes, defaultVer, time) &&
+ engineOk(mani, npmVersion, nodeVersion) &&
+ !mani.deprecated &&
+ !staged[defaultVer]
+ if (ok) {
return mani
}
}
@@ -155,10 +161,10 @@ const pickManifest = (packument, wanted, opts) => {
const [verb, manib] = b
const notavoida = !shouldAvoid(vera, avoid)
const notavoidb = !shouldAvoid(verb, avoid)
- const notrestra = !restricted[a]
- const notrestrb = !restricted[b]
- const notstagea = !staged[a]
- const notstageb = !staged[b]
+ const notrestra = !restricted[vera]
+ const notrestrb = !restricted[verb]
+ const notstagea = !staged[vera]
+ const notstageb = !staged[verb]
const notdepra = !mania.deprecated
const notdeprb = !manib.deprecated
const enginea = engineOk(mania, npmVersion, nodeVersion)
diff --git a/test/index.js b/test/index.js
index 366bcca..682c8d5 100644
--- a/test/index.js
+++ b/test/index.js
@@ -130,6 +130,9 @@ test('ETARGET if range does not match anything', t => {
test('E403 if version is forbidden', t => {
const metadata = {
+ 'dist-tags': {
+ latest: '2.1.0' // do not default the latest if restricted
+ },
policyRestrictions: {
versions: {
'2.1.0': { version: '2.1.0' },
@@ -141,6 +144,9 @@ test('E403 if version is forbidden', t => {
'2.0.5': { version: '2.0.5' },
},
}
+ t.equal(pickManifest(metadata, '2').version, '2.0.5')
+ t.equal(pickManifest(metadata, '').version, '2.0.5')
+ t.equal(pickManifest(metadata, '1 || 2').version, '2.0.5')
t.throws(() => {
pickManifest(metadata, '2.1.0')
}, { code: 'E403' }, 'got correct error on match failure')
@@ -423,6 +429,9 @@ test('accepts opts.before option to do date-based cutoffs', t => {
test('prefers versions that satisfy the engines requirement', t => {
const pack = {
+ 'dist-tags': {
+ latest: '1.5.0' // do not default latest if engine mismatch
+ },
versions: {
'1.0.0': { version: '1.0.0', engines: { node: '>=4' } },
'1.1.0': { version: '1.1.0', engines: { node: '>=6' } },
@@ -430,7 +439,9 @@ test('prefers versions that satisfy the engines requirement', t => {
'1.3.0': { version: '1.3.0', engines: { node: '>=10' } },
'1.4.0': { version: '1.4.0', engines: { node: '>=12' } },
'1.5.0': { version: '1.5.0', engines: { node: '>=14' } },
- },
+ // not tagged as latest, won't be chosen by default
+ '1.5.1': { version: '1.5.0', engines: { node: '>=14' } },
+ }
}
t.equal(pickManifest(pack, '1.x', { nodeVersion: '14.0.0' }).version, '1.5.0')
--
2.39.3 (Apple Git-146)
|
66b46ab
to
5029341
Compare
Previously, there were two problems. First problem, even though we heuristically choose the version that best suits the stated 'engines' restriction, we were skipping that check when the 'defaultTag' (ie, 'latest', typically) version was a semver match. Second problem, the heuristic was improperly being set for 'staged' and 'restricted' packages, resulting in failure to sort those versions properly. Only choose the defaultTag version if it both a semver match, _and_ passes the engines/staged/restricted heuristics, and apply those heuristics properly in the sort that comes later, if the defaultTag version is not used. Related-to: npm/rfcs#405
5029341
to
e170e96
Compare
Rebased, fixed linting (which ironically would have prevented the merge conflict. I begrudgingly have accepted that trailing commas on every line make sense). |
i'd consider this a semver-minor, fwiw. also the farther back in npm majors this can be backported (i understand nobody wants to do that), the sooner the ecosystem may be able to actually treat dropping an engine as a nonbreaking change. |
🤖 I have created a release *beep* *boop* --- ## [9.1.0](v9.0.1...v9.1.0) (2024-07-09) ### Features * [`9f5560f`](9f5560f) [#33](#33) improve heuristics when dist-tags.latest is in range (#33) (@isaacs) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Previously, there were two problems.
First problem, even though we heuristically choose the version that best
suits the stated 'engines' restriction, we were skipping that check when
the 'defaultTag' (ie, 'latest', typically) version was a semver match.
Second problem, the heuristic was improperly being set for 'staged' and
'restricted' packages, resulting in failure to sort those versions
properly.
Only choose the defaultTag version if it both a semver match, and
passes the engines/staged/restricted heuristics, and apply those
heuristics properly in the sort that comes later, if the defaultTag
version is not used.
Related-to: npm/rfcs#405
References