Repository navigation
Fix hosted NuGet lock walk: BOM and other versions (#593, #623) - #1339
Merged
Merged
Conversation
Assisted-by: Claude Code:claude-opus-5-5
Vendored NuGet now reads the source keys and finds the <packageSources>, <packageSourceMapping> and <configuration> anchors through formats::nuget::parse_config, the reader that hosted, upstream restore and VEX already use. The private substring scanner (blank_comments, parse_config_source_keys, attr_value, self_closing_package_sources, insert_at_line) is deleted. User impact: - A close tag written with whitespace (</packageSources >) is now the section that gets extended; vendor used to append a second section NuGet ignores, so restore failed NU1100/NU1403 (#685). - An empty <packageSourceMapping /> is expanded in place instead of left beside a second mapping section. - A section opened and closed on one line receives the source inside it, not before its open tag. - Catch-all keys are written XML-encoded, so a key with & or a quote keeps its identity. - Malformed XML or a repeated section is refused with "malformed XML or a repeated section; not wired" instead of being spliced at the first substring match, as hosted already does. Output bytes for well-formed configs are unchanged. Fixes #685 Refs #594 Assisted-by: Claude Code:claude-opus-5-5
…-config' into agent/v5-nuget-locks
Draft placeholder while the fix is written. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Hosted NuGet rewrote every packages.lock.json entry of the patched id, whatever version it resolved, so a multi-targeting project silently got the patched version's bytes in another framework (#593). Vendored only pinned the matching version but still routed every version of the id to a feed serving one, so the other framework failed NU1102. Both modes now refuse such a lock (redirect_ / vendor_nuget_lock_other_version) before writing anything, and only entries at the patched version are re-pinned. A lock starting with a UTF-8 BOM, which dotnet restores fine, made hosted skip the redirect with exit 0 and vendored fail apply (#623). The lock is now read past the BOM, and the BOM and layout are kept on write. All four lock walkers (vendored pin, hosted redirect, upstream restore, VEX) now share one reader in formats::nuget::lock. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 9, 2026 17:15
Collaborator
Author
|
BugBot review |
Mikola Lysenko (mikolalysenko)
enabled auto-merge
October 9, 2026 17:15
Tanmay Singla (Tanmay182003)
approved these changes
Oct 9, 2026
Mikola Lysenko (mikolalysenko)
disabled auto-merge
October 9, 2026 17:53
Collaborator
Author
|
[final reviewer] I disarmed auto-merge at Generated by Claude Code |
This was referenced Oct 9, 2026
Mikola Lysenko (mikolalysenko)
enabled auto-merge
October 9, 2026 18:23
…eader # Conflicts: # crates/socket-patch-core/src/vendor/nuget_feed.rs
Mikola Lysenko (mikolalysenko)
disabled auto-merge
October 9, 2026 20:41
Tanmay Singla (Tanmay182003)
approved these changes
Oct 9, 2026
# Conflicts: # crates/socket-patch-cli/CLI_CONTRACT.md
Mikola Lysenko (mikolalysenko)
enabled auto-merge
October 9, 2026 22:07
Mikola Lysenko (mikolalysenko)
removed this pull request from the merge queue due to a manual request
Oct 9, 2026
Mikola Lysenko (mikolalysenko)
added a commit
that referenced
this pull request
Oct 10, 2026
Resolve conflicts with #1339 (squash-merged NuGet lock walk: BOM, other versions) by keeping this branch's multi-lock generalization, which already carries #1339's BOM read and other-version refusal per lock. CLI_CONTRACT.md merged word-wise with both sides' additions. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #593
Fixes #623
Summary
NuGet's
packages.lock.jsonwas walked by four separate readers (vendored pin, hosted redirect, hosted upstream restore, VEX). The hosted ones parsed with a bareserde_json::from_strand matched entries by id only. They now share one reader,formats::nuget::lock:parse_lockreads past a leading UTF-8 BOM, as dotnet does.locked_at/locked_at_mutmatch the id (case-insensitive) and the normalizedresolvedversion.other_versionsnames every other version the lock resolves the id at.Root cause
rewrite_nugetand hosted restore matched lock entries by id alone. In a multi-targeting lock (net6.0 → 12.0.3, net8.0 → 13.0.3) hosted re-pinned net6.0 to 13.0.3 with the patched hash, so restore silently gave that framework the patched 13.0.3. Vendored pinned only 13.0.3, but its exact-id mapping still routed every version of the id to a feed that serves one, so net6.0 failed NU1102.serde_jsonrejects a BOM. Hosted then skipped the whole redirect withredirect_nuget_lock_unparseable(exit 0, nothing patched), and vendored failedapply_failed.Fix
redirect_nuget_lock_other_version(hosted warning, dep skipped) andvendor_nuget_lock_other_version(vendored refusal). This is the shared gate the issue proposed.packageSourceMappingpatterns name ids, never versions, so wiring this lock can't be done correctly.contentHash, neverresolved. Upstream restore matches the same way.serialize_json_like: BOM, indent, line endings), not LF pretty-print. The vendored and restore edits already keep it.Per-issue tests
patch::redirect::tests::nuget_lock_with_the_id_at_another_version_is_refusedandnuget_lock_repins_only_entries_at_the_patched_version;vendor::nuget_feed::tests::lock_with_the_id_at_another_version_is_refused_untouched;formats::nuget::lock::tests::*.patch::redirect::tests::nuget_bom_lock_is_redirected_and_keeps_its_bom;vendor::nuget_feed::tests::bom_lock_is_pinned_and_reverted_byte_identically;formats::nuget::lock::tests::bom_lock_parses_like_dotnet_reads_it.Red→green: before the fix, the hosted BOM test hits
redirect_nuget_lock_unparseable, and the other-version test re-pins net6.0 (2 lock edits, no warning).Commands run
cargo test -p socket-patch-core --no-fail-fast(lib + all integration suites, includingredirect_goldenandupstream_restore_golden): greencargo test -p socket-patch-cli --all-features --test e2e_nuget: 21/21cargo test -p socket-patch-cli --all-features --test e2e_nuget_dotnet_build -- --ignored(local SDK 8.0.129): 2/2cargo clippy --workspace --all-features -- -D warnings: cleancargo fmt --all -- --check: clean for touched files.upstream/mod.rsshows a pre-existing local-rustfmt diff that this PR doesn't touch.Includes #1288's commits (approved, about to merge). Follow-up #1340 (member and named locks) builds on this reader.
🤖 Generated with Claude Code
Note
Medium Risk
Changes NuGet hosted redirect and vendored wiring for multi-targeting locks and BOM locks; incorrect behavior could break restores, but the change is fail-closed with new refusal paths and targeted tests.
Overview
Unifies NuGet
packages.lock.jsonhandling across hosted redirect, vendored pin, upstream restore, and VEX via a sharedformats::nuget::lockreader that strips UTF-8 BOMs (like dotnet), matches entries by id + normalized version, and detects when the same id is locked at another version.Hosted and vendored behavior changes (#593, #623): Locks that resolve the patched package id at a different version are refused before any write (
redirect_nuget_lock_other_version/vendor_nuget_lock_other_version), because exact-idpackageSourceMappingcannot serve multiple versions. Hosted re-pins only matching-version entries and updatescontentHashonly (neverresolved); lock output preserves BOM, indent, and line endings. BOM-prefixed locks are no longer treated as unparseable.Vendored
nuget.configwiring now uses the sameformats::nuget::parse_configtokenizer as hosted/restore (replacing ad-hoc comment blanking and key scans), with stricter refusal on malformed or repeated sections.CLI_CONTRACT.mddocuments the new refusal codes and BOM behavior.Reviewed by Cursor Bugbot for commit cbd7bcb. Configure here.