Skip to content

Read and splice nuget.config through formats::nuget in hosted, vendored and restore #594

Description

[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: E11.

Kind: refactor. Source: review §3.7 #3, Part 3.4 and Part 5.4; register E11 (the NuGet half of E10).

Problem

nuget.config is read and spliced by six private code paths with four different XML rules. Only one of them is a real tokenizer.

Readers of the <packageSources> keys:

Splice anchors and removers:

Config file names are spelled four times: redirect::NUGET_CONFIG_FILE_NAMES,`` vendor::nuget_config::CONFIG_NAMES, `hosted/memory/roots.rs` and `formats/registry.rs`. They haven't drifted yet.

The code paths themselves have drifted. The vendored writer is comment-safe; the hosted writer and reader are not. The reader that upstream restore uses (parse_config) and the one the hosted rewriter uses disagree about the same file.

Symptoms

Impact

Every hosted NuGet bug about comments, self-closing sections or attribute spelling has to be fixed up to three times, and the reader each writer trusts is not the one restore and VEX trust. Size: about 250 production lines of regex and substring scanning.

Proposed change

  1. Extend formats::nuget with a span view: parse_config_spans(text) -> Option<NugetConfigSpans> records the byte offsets that every writer needs (the <configuration> open-tag end, the <packageSources> open/close or self-closing span, the <packageSourceMapping> ditto, the last <clear/> end in each, and each <add>/<packageSource> element span with its key). It is computed by the same tokenizer as parse_config, so comments and CDATA are never anchors.
  2. Hosted add_nuget_source and rewrite_nuget take the keys and anchors from it. Delete nuget_package_source_keys, the NUGET_PACKAGE_SOURCES_REGION_RE / NUGET_ADD_KEY_RE statics, the regexes in insert_nuget_source / nuget_mapping_open_end / add_nuget_source, and nuget_after_last_clear's comment masker.
  3. Hosted restore remove_source and vendored excise_source_mapping / parse_config_source_keys use the element spans. Delete both private attr_values and blank_comments (if no other caller remains).
  4. One formats::nuget::CONFIG_FILE_NAMES; delete the other three lists.

This can land as two PRs if it's too big: (a) the span view plus hosted (closes #561 and #585), (b) vendored and restore.

Size and scope

formats/nuget/mod.rs, patch/redirect/mod.rs (NuGet section only), patch/redirect/upstream/nuget.rs, vendor/nuget_feed.rs, vendor/nuget_config.rs, hosted/memory/roots.rs. About +200 / −300 production lines. Out of scope: Maven/Gradle XML (rest of E10) and the packages.lock.json walks (#593).

Acceptance criteria

Dependencies

Supersedes the narrower fix in #561 (either can land first; if #561 lands first, this deletes its remaining regex). Touches rewrite_nuget like #593, so sequence the two. Blocks the Maven/Gradle half of E10.

Activity

  1. added
    arch-auditFiled by a scheduled architecture audit routine (see the architecture review discussion)
    refactorStructural change: duplicated code or logic, missing abstraction, layering, dead code
    on Oct 2, 2026
  2. added a commit that references this issue on Oct 2, 2026
  3. mikolalysenko commented on Oct 2, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triage: priority:p3 (NuGet refactor). The hosted half (part (a): span view + hosted rewriter, closing #561 and #585) is addressed by open PR #597. Vendored and restore (part (b)) remain.


    Generated by Claude Code

  4. mikolalysenko commented on Oct 3, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Shares root cause with #685: the vendored nuget.config writer (vendor/nuget_feed.rs) matches section close tags as literal substrings, so </packageSources > gets a duplicate section. Routing it through formats::nuget as proposed here fixes that symptom too. Will be fixed together.


    Generated by Claude Code

  5. mikolalysenko commented on Oct 5, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Re-checked on main @ 4646693. The hosted part is done: #597 deleted nuget_package_source_keys, and hosted routing and splice anchors now go through formats::nuget::parse_config (used at redirect/mod.rs#L5084, restore and VEX).

    What remains is the vendored side. vendor/nuget_feed.rs still keeps its own reader, parse_config_source_keys,`` and its own find-based splice anchors in `build_config_edit` (`visible.find("")`, the self-closing span at L1114). It doesn't use the insertion spans that #597 added to the shared model. This issue now covers moving those onto `formats::nuget` and deleting the vendored reader.


    Generated by Claude Code

  6. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue for the architecture refactor routine (highest leverage: the vendored nuget.config writer is the last reader outside formats::nuget::parse_config in a free file; routing it through the shared tokenizer deletes blank_comments, parse_config_source_keys, attr_value and self_closing_package_sources and fixes #685). Slice: vendored writer and its idempotence check only. Hosted restore remove_source (upstream/nuget.rs, in a maintainer PR) and the vendored revert excision remain. Branch: arch-refactor/594-vendored-nuget-config. Claim-ID: 2026-10-09T14:56:13Z-ead28c


    Generated by Claude Code

  7. mikolalysenko commented on Oct 9, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Draft PR for the vendored slice (it also fixes #685): #1288.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:claimedagent:triagedarch-auditFiled by a scheduled architecture audit routine (see the architecture review discussion)pm:nugetNuGet / dotnetpriority:p3refactorStructural change: duplicated code or logic, missing abstraction, layering, dead code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions