Repository navigation
Fix VEX gemspec reading commented-out name/version (#1573) - #1582
Merged
Mikola Lysenko (mikolalysenko) merged 4 commits intoOct 15, 2026
Merged
Conversation
Assisted-by: Claude Code:claude-opus-5-5
A gem library's VEX product comes from its root *.gemspec. The reader took the first line that looked like `spec.name = "..."` or `spec.version = "..."`, comments included, so a commented-out `# spec.version = "0.0.1"` above `spec.version = Acme::VERSION` gave pkg:gem/acme@0.0.1, and a commented `# spec.name = "acme-legacy"` renamed the product. Consumers matching VEX statements to their SBOM then never applied them. The gemspec is now read as Ruby sees it: `#` comments outside strings, =begin/=end blocks and heredoc bodies are skipped, and the last live assignment wins, so a computed version drops the version as documented. Fixes #1573 Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 15, 2026 17:04
Read the gemspec through formats::gem's for_each_code_line, the lexer the Gemfile readers already use, instead of a second copy. It also stops at __END__ and knows lower-case and backtick heredocs, so a DATA section or such a heredoc can't set the product's version. Only assignments to the Gem::Specification.new block parameter count when the file names one, so a later `ext.name = ...` in the same file can't rename the product now that the last assignment wins. Assisted-by: Claude Code:claude-opus-5-5
Collaborator
Author
|
BugBot review Generated by Claude Code |
A one-line spec such as
`Gem::Specification.new { |s| s.name = "a"; s.version = "1" }`, or an
assignment after the `do |s|` on the opener line, was not read: the
product fell back to the file name with no version. Each line's code
is now split into statements on `;`, after any block opener.
Assisted-by: Claude Code:claude-opus-5-5
Collaborator
Author
|
BugBot review Generated by Claude Code |
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 9de072d. Configure here.
Tanmay Singla (Tanmay182003)
approved these changes
Oct 15, 2026
Mikola Lysenko (mikolalysenko)
deleted the
agent/fix-gemspec-comment-parse
branch
October 15, 2026 18:57
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 #1573
Summary
vex(andscan/apply/vendor --vexwithout--vex-product) names a gem library's top-level product from its root*.gemspec. A commented-out assignment used to win over the live one:# spec.version = "0.0.1"abovespec.version = Acme::VERSIONgavepkg:gem/acme@0.0.1. It now givespkg:gem/acme, because a computed version is dropped as documented.# spec.name = "acme-legacy"abovespec.name = "acme"gavepkg:gem/acme-legacy. It now givespkg:gem/acme.Root cause
parse_gemspec(crates/socket-patch-core/src/vex/product.rs) took the first line whose left side of=ended in.name/.versionand whose right side was a quoted literal. It never skipped Ruby comments. Because it also skipped computed right-hand sides and kept searching, the first literal anywhere in the file won, even when Ruby's effective value was a later computed one.Fix
parse_gemspecnow reads the file throughformats::gem::manifest::for_each_code_line, the Ruby line lexer the Gemfile readers already use (madepub(crate)). That lexer skips#comments outside strings,=begin/=endblocks, heredoc bodies and everything after__END__.Gem::Specification.load). If it is computed, the version is dropped and the name falls back to the file stem.Gem::Specification.new do |spec|block parameter, only assignments to that receiver count, so a helper'sext.name = …can't rename the product.;(outside strings), after any block opener, so a one-lineGem::Specification.new { |s| s.name = "a"; s.version = "1" }is read. This came from Bugbot's finding on c6b44b2.=~and==comparisons are still not taken for assignments.No wrapper changes are needed:
npm/,pypi/andgem/don't read gemspecs./code-review high
I ran it on the first revision. Its main point was that the PR duplicated the crate's existing Ruby lexer, so the second commit reuses it. That also fixes the findings about
__END__, lower-case and backtick heredocs, and the per-line quote handling. I also took the receiver finding (match the spec's block parameter), dropped the redundant\rstrip, and dropped theVec::remove(0)allocation note along with the duplicated code. Not changed: a bare<<IDclosing on an indentedIDline, and1<<SHIFTread as a heredoc opener. Both are limitations of the shared lexer that every Gemfile reader already has, and neither shape is plausible in a gemspec. Changing them belongs in a lexer fix, not this PR.Test evidence
vex::product::tests::detect_gemspec_ignores_commented_assignmentscovers both shapes from VEX gemspec product detection reads commented-out# spec.name =/# spec.version =lines, so the document names the wrong product or version #1573 and the variants the issue lists: trailing#comments,=begin/=end, heredocs (bare and quoted),<<inside a string, a__END__DATA section, another receiver's.name/.version, assignments on the block-opener line and after;, last-assignment-wins, a trailing comment after a live literal, and the stem fallback.assertion failed: commented literal version above a computed one; left: Some("pkg:gem/acme@0.0.1") right: Some("pkg:gem/acme")cargo test -p socket-patch-core --all-features --lib vex::productgives 146 passed (194 withformats::gem).cargo fmt --all -- --check: clean.cargo clippy --workspace --all-features -- -D warnings: clean.cargo test --workspace --all-features --no-fail-fast: 14,575 passed, 10 failed. All 10 come from the sandbox and none touch this change. Nine are permission-based failure-injection tests (chmod-made unwritable or unremovable paths) that can't fail when tests run as root. The tenth,e2e_bun_lockb::binary_shared_bundled_record_hosted_pin_is_managed, needs patches-api.socket.dev, which this sandbox can't reach (tunnel error). CI runs these normally.Per-issue checklist
# spec.name =/# spec.version =lines, so the document names the wrong product or version #1573 commentedversion: case "commented literal version above a computed one"# spec.name =/# spec.version =lines, so the document names the wrong product or version #1573 commentedname: case "commented name above the live one"# spec.name =/# spec.version =lines, so the document names the wrong product or version #1573=begin/=endand heredocs: cases "=begin / =end block", "heredoc body", "quoted heredoc identifier"🤖 Generated with Claude Code
Generated by Claude Code