Repository navigation
Look up NuGet packages by normalized version in the crawler (#1202) - #1239
Mikola Lysenko (mikolalysenko) wants to merge 3 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
Agent-mode apply, rollback and VEX locate a NuGet package's directory through the crawler's find_by_purls, which keyed versions by lowercase only. NuGet's identity is the normalized version, so a project pinned as 1.0.0.0 never found the global folder's foo/1.0.0/, and a packages.config folder Foo.1.0.0.0/ was invisible to a purl at 1.0.0. The lookup now goes through the same normalize_nuget_version the vendored feed and lock match use: the global folder under the normalized version (then the as-written one), and the legacy folder fallback by case-insensitive id plus normalized version. Spellings that already matched still match the same directory. Refs #1202 Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Assisted-by: Claude Code:claude-opus-5-5
|
Ready for review at
Generated by Claude Code |
Final review briefWhat it does: The NuGet crawler's Risk: low. The change is lookup-only and confined to one function. Look here:
Verified:
Changes I made: none. Open questions (non-blocking):
Auto-merge is armed: approving sends this straight to the merge queue. Generated by Claude Code |
A cache or packages/ folder holding both spellings of one release (foo/1.0.0.0/ and foo/1.0.0/) now resolves to the folder main always picked, the as-written one, and only falls back to the normalized spelling. The legacy fallback likewise prefers the case-insensitive <name>.<version> match over an equal release spelled differently. Refs #1202 Assisted-by: Claude Code:claude-opus-5-5
|
[agent] Both open questions in the final review were right: the description overstated the "no change" claim. Fixed in
Generated by Claude Code |
|
BugBot review Generated by Claude Code |
Assisted-by: Claude Code:claude-opus-5-5
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 034c189. Configure here.
Final review brief (updated for
|
LLM Description written by Claude Code:claude-opus-5-5
Refs #1202 (the crawler slice; #1230 is the
PurlKeyslice; theformats::nugetmove remains).Summary
NuGet's package identity is the normalized version (
1.0.0.0=1.0.0=1.00.0). The vendored feed, the lock match and upstream restore already usevendor::nuget_feed::normalize_nuget_version, but the NuGet crawler'sfind_by_purls(agent-mode apply, rollback and the VEX installed lookup) only lowercased. So a purl at@1.0.0.0never found the global folder'sfoo/1.0.0/, and apackages.configfolderFoo.1.0.0.0/was invisible to a purl at@1.0.0. This PR routes the crawler's lookup through the same normalizer.Why (leverage)
doc/06-discovery-vex.md(E93 passage).packages/Foo.1.0.0.0for@1.0.0, and the global-folderfoo/1.0.0for@1.0.0.0").formats::nugetremains.crawlers/nuget_crawler.rs), which no other open PR touches. S 0.What changed
find_by_purls_sync: the global layout tries<id lower>/<version lower>/first (what main tried), then<id lower>/<normalized>/when that spelling differs. The exact-case legacy<Name>.<Version>/probe is unchanged.find_legacy_dir_case_insensitivebecamefind_legacy_dir_by_identity, through a newlegacy_dir_is: at any.boundary, the id matches case-insensitively and the non-empty version normalizes to the purl's. It's a superset of the olddir.to_lowercase() == "<name>.<version>".to_lowercase()match. The old match runs first over the listing, and the identity match only runs when it finds nothing, so a root holding bothfoo.1.0.0andFoo.1.0.0.0keeps main's pick. The verification gate is unchanged.Deleted
git diff --stat: production +47/−19 (the lowercase-only global path and target-string match), tests +116/−4 (3 call sites renamed).Behavior
For spellings that already resolved: none. Every probe main made runs first, in main's order, so the same directory is found, even in a cache holding two spellings of one release (
034c189, after the final review:test_find_by_purls_as_written_spelling_wins_over_normalized). The new behavior: a non-normalized version (4-part with a zero revision, zero-padded segments,+buildmetadata) now finds the package that NuGet considers the same release.Foo@1.0.0.1is still not1.0.0, andFoo.Bar.1.0.0is still notFoo. The test-onlyoracle.rskeeps main's rule. Its randomized versions are all normalized, so the equivalence test still passes, which shows nothing changes for normalized spellings.Test evidence
test_find_by_purls_global_cache_normalizes_version,test_find_by_purls_legacy_layout_normalizes_versionandlegacy_dir_is_matches_identity_onlyfail. They pass on the branch.test_find_by_purls_global_cache_as_written_version_still_foundpins the fallback to the old path.cargo clippy --workspace --all-features -- -D warnings: clean.cargo test -p socket-patch-core --lib: 5891 passed, plus 4 root-only failures that also fail on main in this sandbox (copy_tree::relax_loop_must_not_traverse_symlinked_root,vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry,pypi_poetry::wire_write_failure_maps_error_and_leaves_lock_untouched,pypi_requirements::wire_failure_rolls_back_already_written_files).crawler_nuget_e2e28,e2e_nuget21,ecosystem_dispatch_e2e40,in_process_remote_ecosystems_apply12,in_process_rollback_all_ecosystems27,in_process_scan27 ande2e_vex38: all passed. There's no .NET SDK in the sandbox, soe2e_nuget_dotnet_buildruns in CI.Risk
Low. The change is one lookup function and is strictly additive for spellings that already matched. The fallback listing is only consulted after the direct probes miss, as before.
🤖 Generated with Claude Code
https://claude.ai/code/session_014zP8cfveTMRsL71USbtgAx
Note
Low Risk
Scoped to NuGet directory lookup in
find_by_purls; prior probe order is preserved for spellings that already matched, with additive fallbacks only.Overview
NuGet
find_by_purlsnow resolves packages using NuGet’s normalized version identity, aligning the crawler with the vendored feed and lock matching (normalize_nuget_version).For the global cache, lookup tries the lowercased PURL version path first, then falls back to the normalized folder (e.g.
@1.0.0.0→foo/1.0.0/). For legacypackages/<Id>.<Version>/,find_legacy_dir_case_insensitiveis replaced byfind_legacy_dir_by_identity, which still prefers an exact case-insensitive spelling match, then matches folders whose id and normalized version equal the PURL (splitting at every.for dotted ids). As-written spellings still win when both exist; returned rows keep the requested PURL.Extensive unit tests cover normalization, legacy cross-spelling, and regression guards.
Reviewed by Cursor Bugbot for commit 034c189. Configure here.
Generated by Claude Code