You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: discussion #560 register.
Kind: refactor. Source: review Part 5.4 ("Gem: … its own section model … two DEPENDENCIES-name parsers"), register E19 (gem half).
Problem
formats/gem says it is the one read model for Gemfile.lock, but hosted and vendored mode each re-scan the lock with their own section model and their own DEPENDENCIES-entry grammar. Verified on 045d7ec:
section_span(lines, header) / section_end: the first line equal to header, plus find_our_path_section and find_path_section (#L1926-L1942, #L2299-L2317)
dep_entry_name: at_indent(2) + find([' ', '(', '!']), and spec_entry_name beside it
So there are three section models and three DEPENDENCIES-name rules (the review counted two of the latter). The name rules agree on every Bundler-written entry I tried. The section models have already drifted: vendored section_span(&lines, "GEM") sees only the first GEM section, while the shared reader and hosted see all of them. Bundler 2 writes one GEM section per source, so a gem resolved from any source but the first can't be vendored. That bug is filed separately as #779, since it can be fixed before this refactor.
Any future change to section or DEPENDENCIES handling, such as the platform-suffixed specs, a GEM section with several remotes, or PLUGIN SOURCE, has to be made three times.
Size: formats/gem is 1,149 lines, vendor/gem.rs 7,576 (2,461 production).
Proposed change
Make formats::gem the single source of line spans, and have both writers splice through it:
Extend GemfileLock with what the writers need: each Section's end line (exclusive, the next column-0 header), and the DEPENDENCIES entries as (line_no, name, pinned) using one name rule. Expose gem_sections(), path_sections(), dependencies() and section(header).
Hosted: build converge_gem_lock_source's section and DEPENDENCIES lookups from parse(lk). DeleteGemLockSection, its header walk and gem_lock_dependency_name.
Vendored: replace section_span, section_end, dep_entry_name, spec_entry_name, find_our_path_section and find_path_section with the parsed model. Delete them. edit_lock looks the spec up across every GEM section, which fixes Vendored gem refuses a gem whose spec is not in the lock's first GEM section #779 if it is still open.
Land it as two PRs, hosted first (smaller), then vendored. Neither changes output bytes.
Size and scope
Est. +120 / −250 production lines across formats/gem/mod.rs, formats/gem/hosted.rs and vendor/gem.rs. Out of scope: the Gemfile (Ruby source) models in formats/gem/manifest.rs and rewrite_gem's CHECKSUMS regexes (review Part 3, #340), and the hosted ↔ vendored takeover logic (#775, PR #776).
Acceptance criteria
GemLockSection, gem_lock_dependency_name, section_span, section_end, dep_entry_name and spec_entry_name no longer exist. grep -n '"DEPENDENCIES"' crates/socket-patch-core/src finds the header only in formats/gem/mod.rs and tests.
Byte-identical output: e2e_redirect_gem_build, e2e_vendor_gem_build, the hosted gem goldens and the vendor/gem.rs unit tests stay green unchanged.
New formats::gem tests: section end lines with CRLF and trailing blank lines, a two-GEM-section lock, and DEPENDENCIES entries rack, rack!, rack (~> 3.1), rack (= 3.2.6)! naming rack with the right pinned flag.
A hosted test and a vendored test on a lock whose target gem is in the second GEM section.
Dependencies
Open PRs #768 and #776 edit vendor/gem.rs and formats/gem/mod.rs, so start after they merge. Blocks nothing; it makes #779's fix a deletion.
[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: discussion #560 register.
Kind: refactor. Source: review Part 5.4 ("Gem: … its own section model … two DEPENDENCIES-name parsers"), register E19 (gem half).
Problem
formats/gemsays it is the one read model forGemfile.lock, but hosted and vendored mode each re-scan the lock with their own section model and their own DEPENDENCIES-entry grammar. Verified on045d7ec:formats::gem::parse(inventory, VEX,lock_lists_direct_dependency, upstream restore)Sectionfor everyGEM/PATH/GIT/PLUGIN SOURCEheader, with remotes and spec linessplit([' ', '(', '!'])(mod.rs#L286-L298)formats::gem::hosted::converge_gem_lock_sourceGemLockSection(hosted.rs#L26-L35),GEMheaders only, built by a second header walkgem_lock_dependency_name:trim_start,split(" ("),trim_end_matches('!')vendor/gem.rssection_span(lines, header)/section_end: the first line equal toheader, plusfind_our_path_sectionandfind_path_section(#L1926-L1942,#L2299-L2317)dep_entry_name:at_indent(2)+find([' ', '(', '!']), andspec_entry_namebeside itSo there are three section models and three DEPENDENCIES-name rules (the review counted two of the latter). The name rules agree on every Bundler-written entry I tried. The section models have already drifted: vendored
section_span(&lines, "GEM")sees only the firstGEMsection, while the shared reader and hosted see all of them. Bundler 2 writes oneGEMsection per source, so a gem resolved from any source but the first can't be vendored. That bug is filed separately as #779, since it can be fixed before this refactor.Symptoms and impact
GEMsection).GEMsection with several remotes, orPLUGIN SOURCE, has to be made three times.Size:
formats/gemis 1,149 lines,vendor/gem.rs7,576 (2,461 production).Proposed change
Make
formats::gemthe single source of line spans, and have both writers splice through it:GemfileLockwith what the writers need: eachSection's end line (exclusive, the next column-0 header), and the DEPENDENCIES entries as(line_no, name, pinned)using one name rule. Exposegem_sections(),path_sections(),dependencies()andsection(header).converge_gem_lock_source's section and DEPENDENCIES lookups fromparse(lk). DeleteGemLockSection, its header walk andgem_lock_dependency_name.section_span,section_end,dep_entry_name,spec_entry_name,find_our_path_sectionandfind_path_sectionwith the parsed model. Delete them.edit_locklooks the spec up across everyGEMsection, which fixes Vendored gem refuses a gem whose spec is not in the lock's first GEM section #779 if it is still open.Land it as two PRs, hosted first (smaller), then vendored. Neither changes output bytes.
Size and scope
Est. +120 / −250 production lines across
formats/gem/mod.rs,formats/gem/hosted.rsandvendor/gem.rs. Out of scope: the Gemfile (Ruby source) models informats/gem/manifest.rsandrewrite_gem's CHECKSUMS regexes (review Part 3, #340), and the hosted ↔ vendored takeover logic (#775, PR #776).Acceptance criteria
GemLockSection,gem_lock_dependency_name,section_span,section_end,dep_entry_nameandspec_entry_nameno longer exist.grep -n '"DEPENDENCIES"' crates/socket-patch-core/srcfinds the header only informats/gem/mod.rsand tests.e2e_redirect_gem_build,e2e_vendor_gem_build, the hosted gem goldens and thevendor/gem.rsunit tests stay green unchanged.formats::gemtests: section end lines with CRLF and trailing blank lines, a two-GEM-section lock, and DEPENDENCIES entriesrack,rack!,rack (~> 3.1),rack (= 3.2.6)!namingrackwith the rightpinnedflag.GEMsection.Dependencies
Open PRs #768 and #776 edit
vendor/gem.rsandformats/gem/mod.rs, so start after they merge. Blocks nothing; it makes #779's fix a deletion.