Skip to content

Fix/version discovery range pruning - #1815

Open
georgelemon wants to merge 6 commits into
nim-lang:masterfrom
georgelemon:fix/version-discovery-range-pruning
Open

Fix/version discovery range pruning#1815
georgelemon wants to merge 6 commits into
nim-lang:masterfrom
georgelemon:fix/version-discovery-range-pruning

Conversation

@georgelemon

@georgelemon georgelemon commented Aug 6, 2026

Copy link
Copy Markdown

Related to #1814

The mechanism now

Discovery only ever sees versions that could actually be selected:

  1. Per-branch range filter (in getMinimalFromPreferred): each requirement branch filters discovered versions against its own range. Out-of-range historical versions (tim 0.2.0, watchout 0.2.0/0.2.1, supranim 0.1.0–0.1.4) never reach requirement processing → libffi/httpx/websocketx/libevent are never touched.
  2. Range intersection: when a package's versions disagree on a requirement — supranim 0.1.5 says ozark >= 0.1.4, 0.1.6 says >= 0.1.5processRequirements merges them into the intersection >= 0.1.5 and discovers only that. ozark 0.1.4 is never discovered, so its dead parsesql URL is never probed at all.
  3. Discovery never blocks on a prompt: during collectAllVersions, GIT_TERMINAL_PROMPT=0 is set (respecting user overrides, restored afterwards). Any dead URL that is still probed (e.g. a genuinely dead direct requirement) fails fast and the version is excluded. Actual installs run outside this window, so private repos still get an interactive prompt.
  4. Failures now propagate: processRequirements re-raises, the caller records the requirement in failedReqs, and dependent versions are excluded cleanly; collectAllVersions tolerates failed top-level requirements (and consumes failed futures so chronos stays quiet).

Why it's provably safe

  • Per-branch filter: a version outside a branch's range can't be selected by that branch, and branches are unioned — so no selectable version is ever lost.
  • Intersection merge: any version outside the intersection of all constraints fails at least one constraint, so it can't be in any valid solution. Dropping it from discovery is safe.
  • The solver's constraints still come from the raw requires stored on each version in the table, not from the merged range. The merged range only decides what gets fetched/discovered; it never relaxes what the solver enforces. So with >= 0.1.4 and >= 0.1.5 both present, the solver still always picks 0.1.5 — the merged range just stops wasting work on 0.1.4.

Net result for booyaka now: supranim >= 0.1.5 → intersect → ozark >= 0.1.5 → discover only 0.1.5 → no parsesql, no prompt, build succeeds.

Git prompting: before vs now per scenario

Scenario Before Now
Dead URL from an out-of-range old version (tim 0.2.0 → libffi, watchout 0.2.1 → httpx) prompted never processed → no prompt
Dead URL from an in-range old version that can't win (ozark 0.1.4 → parsesql) prompted never discovered (intersection) → no prompt, no probe
Genuinely dead direct requirement prompted and hung probed once with GIT_TERMINAL_PROMPT=0 → fails fast → clean Missing dependencies error → no prompt
Private repo actually needed prompted during discovery and install installs stay interactive; ssh keys / credential helpers work non-interactively → no prompt, works

…tags

Signed-off-by: George Lemon <georgelemon@protonmail.com>
=> >= 0.1.5) so versions that can never be selected - and their
historical requirements (often pointing at deleted repos), are never
processed. Keep installs interactive so private repos still work.

Signed-off-by: George Lemon <georgelemon@protonmail.com>
Signed-off-by: George Lemon <georgelemon@protonmail.com>
@jmgomez

jmgomez commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

A couple of things before this can get a proper review. When a change is largely AI-produced, please verify it's sound before submitting ie "Why it's provably safe" section isn't evidence. The intersection logic in processRequirements merges requirements coming from different versions of the same package, which changes resolution semantics — that needs tests demonstrating the solver still finds a solution when it has to fall back to an older version of a dependency

Also please split this in two, both the PR and the issue:

  1. Not blocking on git credential prompts during discovery — that's the actual reported symptom and is reviewable on its own.
  2. The discovery range pruning — a resolver change that deserves its own discussion.

The GIT_TERMINAL_PROMPT handling during version discovery belongs to the
separate 'don't block on git credential prompts' change; this branch keeps
only the discovery range pruning.
Intersecting same-name requirements coming from different versions of the
same package can drop a version the solver needs when it has to fall back
to an older version of that package (e.g. when the newest version's own
dependencies are unresolvable). Keep distinct requirement ranges instead —
only de-duplicate exact duplicates — and remove the now-unused
intersectVersionRanges/isSimpleRange helpers.

Add comprehensive offline resolver tests covering range pruning (>=, <=,
==, >X&<Y, ^=, ~=, any, multi-branch), failedReqs exclusion (satisfied and
unsatisfied), multiple packages requiring the same dependency with
different ranges, and fallback to older versions.
Signed-off-by: George Lemon <georgelemon@protonmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants