Skip to content

Keep NuGet patches installed with <clear /> and NuGet.config - #284

Merged
Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
claude/nuget-patch-annotation-fixes
Sep 28, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
claude/nuget-patch-annotation-fixes

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Hosted and vendored NuGet patches now install on projects whose nuget.config starts a section with <clear />, and on projects whose config file is spelled NuGet.config or NuGet.Config. Before this, dotnet restore failed with NU1100 or NU1101 in both cases. The work came out of the depscan NuGet patch SBOM annotation effort; its depscan PRs follow.

<clear /> dropped the Socket source (hosted)

Hosted mode inserted the Socket package source right after the <packageSources> open tag. When the config already had a mapping section, it inserted the Socket mapping right after <packageSourceMapping> too. A <clear /> at the top of either section, which is common in corporate configs, then threw the Socket entry away:

  • a <clear /> in <packageSources> failed restore with NU1100, reproduced on SDK 6.0, 8.0 and 10.0;
  • a <clear /> in <packageSourceMapping> failed with NU1101.

Both entries now go after the last <clear /> in their section. Vendored mode already appended after existing entries, so it wasn't affected.

Config spelling shadowed the user's config (hosted and vendored)

NuGet reads only the first of nuget.config, NuGet.config and NuGet.Config in a directory; this was confirmed with real SDKs.

  • Hosted: only read nuget.config. With a project config named NuGet.config, it created a new nuget.config next to it. That hid the project's private feed, and restore failed with NU1101.
  • Vendored: probed nuget.config and then NuGet.Config, so it missed NuGet.config the same way.

Both modes now edit whichever spelling exists, and create nuget.config only when none does. The in-memory hosted engine (hosted_memory/roots.rs, redirect.rs) and scan/hosted.rs pick up the same candidate list.

Tests

  • New unit tests in patch/redirect/mod.rs and vendor/nuget_feed.rs, plus an in-process get --mode hosted test in in_process_get_hosted_ecosystems.rs. Each fails without its fix.
  • cargo test -p socket-patch-core --lib nuget passes (186 tests), and so does cargo test -p socket-patch-cli --test in_process_get_hosted_ecosystems nuget. The broader core and CLI suites and e2e_vex_lockfile also passed, as did the CI clippy command.
  • Hosted: both fixes were reproduced and verified with a real dotnet restore.
  • Vendored: the NuGet.config gap is covered only by the unit test.

Failures already on main that this PR does not touch:

  • one vlt_heal test fails when run as root;
  • --all-targets clippy fails on covgap_commands_rollback.rs, which CI doesn't lint;
  • cargo fmt --check fails across about 60 files, and CI has no fmt step.

Only the changed lines are formatted, to keep the diff small next to other work in redirect/mod.rs and vendor/.

🤖 Generated with Claude Code


Note

Medium Risk
Changes NuGet config rewrite semantics for hosted and vendored flows; mistakes could break dotnet restore for corporate configs, but behavior is narrowly scoped with targeted regression tests.

Overview
Fixes two NuGet restore failures in hosted redirects and vendored wiring that showed up as NU1100 / NU1101 after patching.

<clear /> in nuget.config: Socket package sources and packageSourceMapping entries were inserted at the top of <packageSources> / <packageSourceMapping>, so NuGet discarded them when a corporate config started the section with <clear />. Inserts now go after the last <clear /> in that section via nuget_after_last_clear.

Config filename casing: NuGet reads the first of nuget.config, NuGet.config, and NuGet.Config. Hosted mode always wrote nuget.config; vendored mode skipped NuGet.config. On case-sensitive filesystems that shadowed the project’s real file and dropped private feeds. Both paths now share NUGET_CONFIG_FILE_NAMES and edit whichever file is present (scan/hosted discovery lists all three spellings).

Unit tests cover clear-tag placement and in-place rewrites; an in-process hosted get test and a vendored wiring test assert mixed-case configs stay intact without a shadow file.

Reviewed by Cursor Bugbot for commit 375681d. Configure here.

Hosted mode inserted the Socket package source (and, when the config
already had a packageSourceMapping, its mapping) directly after the
section's open tag. A config that starts the section with <clear />,
common in corporate setups, then discarded the Socket entry, so
dotnet restore failed NU1100 / NU1101 for the patched package. The
entries now land after the last <clear /> in their section.

Assisted-by: claude-code:claude-opus-5-5
NuGet reads the first of nuget.config, NuGet.config and NuGet.Config
in a directory. Hosted mode only read nuget.config and vendored mode
skipped NuGet.config, so on a case-sensitive filesystem a project
whose config used another spelling got a new nuget.config that
shadowed it. Its sources and mappings were ignored and packages from
private feeds failed to restore. Both modes now edit the existing file
in place and only create nuget.config when no spelling exists.

Assisted-by: claude-code:claude-opus-5-5

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 375681d. Configure here.

Comment thread crates/socket-patch-core/src/patch/redirect/mod.rs
… inserts

The after-<clear /> insert found section bounds with literal
`</packageSources>` / `</packageSourceMapping>` and the mapping open tag
with a literal `<packageSourceMapping>`. A close tag with whitespace before
`>` sent the insert back ahead of the `<clear />`, which drops it; a
spaced mapping open tag authored a duplicate section. A commented-out
`<clear />` also became the anchor, splicing the Socket source inside the
comment. Match tags with the same whitespace/attribute tolerance as the
rest of the rewriter and skip comments.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPYQfCTLY7F4eQTa8hjinL
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Bun patch compatibility / native (macos-latest, 1.1.38) failed on 02ee0a6. I don't think this PR caused it. Only the hosted cells failed: patched bytes were missing and the hosted-then-vendored conversion reported 0 patches. The vendored cells, which don't need the network, all passed. PR #283's native (macos-latest, 1.0.0) job failed the same way in the same minute, and its log shows urlopen error [Errno 8] nodename nor servname provided, or not known, which means the macOS runner couldn't resolve a hostname. This PR only changes NuGet code, which the Bun harness doesn't run. No code fix applies. I'll re-run the failed job once when the run finishes.


Generated by Claude Code

@mikolalysenko
Mikola Lysenko (mikolalysenko) merged commit f6b7fb9 into main Sep 28, 2026
607 of 612 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the claude/nuget-patch-annotation-fixes branch September 28, 2026 12:00
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Summary of the follow-up work on this PR. It was merged at 12:00 UTC.

Review comments

  • Bugbot "Naive tags break after-clear insert": fixed in 965995e. Section close tags now match with whitespace before >. The <packageSourceMapping> open tag now matches with whitespace or attributes, which also stops a spaced open tag from producing a duplicate mapping section. One part of the finding was wrong: the literal find only ran when the literal tag was present, so the mapping could never be spliced inside the open tag. The thread is resolved.

Found in my own review

  • A commented-out <!-- <clear /> --> was treated as a real <clear />, so the Socket source was spliced inside the comment and NuGet ignored it. Fixed in 965995e: the search skips comments.
  • I checked the vendored path, the CLI's list of config file names, and the Windows case-insensitive check for an existing config file, and found no other defects. The Windows check dates from before this PR.

Commits

  • 965995e fix(core/redirect): match NuGet section tags tolerantly for <clear /> inserts. Adds nuget_after_clear_tolerates_spaced_tags and nuget_commented_clear_is_not_an_anchor; both failed on the code before the fix.
  • 02ee0a6 fix(core/redirect): slice bytes, not str, when masking comments (a clippy lint fix).

CI on 02ee0a6

  • The CI workflow passed, including clippy, the Linux, macOS and Windows tests, test-release, coverage, and the NuGet Docker end-to-end test. All the other compatibility matrices passed.
  • Only four Bun patch compatibility jobs failed: native (macos-latest, …) for 1.1.38, 1.2.23, 1.3.10 and 1.4.2. The macOS runners had network trouble at the time: the hosted cells lost their connection or timed out on bun install, while the vendored cells passed. WS5: one VendoredBackend for vendored apply/revert/repair; cut repair's ledger rebuild #283 failed the same way in the same minute, with urlopen error [Errno 8] nodename nor servname provided. I queued one re-run of those four jobs at 11:53, and it had not finished when the PR merged.

Still open

  • Nothing in this PR's code. The Bun re-run result is still pending.

Generated by Claude Code

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.

3 participants