Repository navigation
Rebuild gem native extensions from a relative crawl root - #2048
Conversation
Agent-mode apply rebuilds a patched gem's C extension by running Ruby from the project dir, and RubyGems runs extconf.rb from the gem's ext dir. The copy's paths came from the crawl root as given, so with the default `--cwd .` (Bundler `path vendor/bundle`) GEM_PATH was a relative `./vendor/bundle/ruby/<abi>`. From the ext dir that names nothing, so an extconf.rb that activates a gem from the copy's own home failed. nokogiri's (`mini_portile2`) fails this way, and apply reported native_extension_build_failed and put the original back. A relative `--cwd proj` failed one step earlier: Ruby, run from `proj`, could not load `proj/vendor/.../x.gemspec`, so the patch was refused as native_extensions_unsupported. GemCopy::of now makes the copy's path absolute, so the spec path, GEM_PATH, gem dir and extension dirs are absolute for both the probe and the build. The marker still records extension dirs relative to the home. Found by smoke-testing 5.1.0. Before this fix, a hand-written patch to ext/nokogiri/nokogiri.c on nokogiri 1.19.7 (ruby platform, packaged libxml2) failed to rebuild under plain `socket-patch apply`. With it, the extension rebuilds in about 28s, Ruby loads the patched constant, `apply --check` is in sync, and rollback restores the original build. The new capstone native_patch_builds_from_a_relative_crawl_root patches extconf.rb to activate a helper gem installed in the same home, then applies with `--cwd proj` and with the default root. It fails without this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Keep a rooted path as is, so Windows doesn't put a drive on `/h` and break the gem_ext unit tests. Make only a relative root absolute, with relpath::absolute_lexically, which drops `..` the way Ruby's File.expand_path does and falls back to the given path on error instead of reading the copy as "not a RubyGems install". - Unit test: a relative `..` path becomes absolute and normalized. - Capstone: build the helper gem outside the crawled vendor/bundle tree, and also run `apply --check` and `rollback` on the default root. - Move walk_files' doc comment back onto it, and drop the now-stale "relative crawl root" reason from ext_dir_label's doc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Labeled Ready for review by the burn-down agent.
Generated by Claude Code |
Final review briefWhat it does. Agent-mode Risk: low. One function changes, in agent-mode gem native rebuilds only. Rooted paths are kept as they are. The build marker still records extension dirs relative to the home, so existing markers still match. Look here
Verified
Changes I made. No code changes. I fixed one sentence in the PR description: it said Open questions. None. Auto-merge (squash) is armed, so approving sends this straight to the merge queue. Generated by Claude Code |
Summary
5.1.0 release blocker found while smoke-testing the headline feature (agent-mode gem native-extension rebuild, #1996/#1998) on a real nokogiri.
Agent-mode
applyrebuilds a patched gem's C extension by running Ruby from the project dir, and RubyGems runsextconf.rbfrom the gem'sext/dir. The copy's paths came straight from the crawl root, so they were relative:--cwd .with Bundlerpath vendor/bundle(the common CI setup):GEM_PATH=./vendor/bundle/ruby/3.4.0names nothing from the ext dir. nokogiri'sextconf.rbthen can't activatemini_portile2from the same home:Could not find 'mini_portile2' (~> 2.8.2). Apply reportsnative_extension_build_failedand puts the original back, so the patch is never applied.--cwd proj: Ruby runs fromprojand can't loadproj/vendor/.../nokogiri-1.19.7.gemspec, so the patch is refused withnative_extensions_unsupported.GemCopy::ofnow makes the copy's path absolute (relpath::absolute_lexically:std::path::absolutewith..dropped lexically, as Ruby'sFile.expand_pathdoes), so the spec path,GEM_PATH, gem dir and extension dirs are absolute for both the probe and the build. The build marker still records extension dirs relative to the home, so marker matching is unchanged.Test plan
native_patch_builds_from_a_relative_crawl_root: the patch changesextconf.rbto activate a helper gem installed in the copy's home (as nokogiri does withmini_portile2), then applies with--cwd projand with the default root. It fails on main and passes with the fix.cargo test -p socket-patch-cli --test e2e_gem_native_ext_build -- --include-ignored: 8/8 pass locally (Ruby 3.4.10, macOS arm64).cargo test -p socket-patch-core --lib gem_ext: 18 pass.cargo fmt --checkand the CI clippy invocation are clean.ext/nokogiri/nokogiri.cpatch rebuilds in about 28s, Ruby loads the patched constant,apply --checkis in sync, androllbackrestores the original build./code-review high
I fixed: the Windows rooted-path break in the unit tests,
..normalization to match Ruby'sFile.expand_path, the fallback when making the path absolute errors, the misplaced doc comment, the helper gem being built inside the crawled tree, the staleext_dir_labeldoc, and the missingapply --check/rollbackcoverage on the default root. I didn't fix:RubyEnv.cwd/ the crawl root absolute at the top: the fix belongs at the copy's paths, which are what the build runs on.ruby_candidatescompares canonical paths first, so its relative fallback only applies when canonicalize fails. Changing the CLI-wide--cwdspelling would change reported paths in every ecosystem, which is out of scope for a release blocker.homein two refusal/restore details: these are error details for a host-local install, and an absolute path is clearer there.package_pathkeeps the user's spelling.write_manifestfor the two-file record: this test is the only multi-file case, and the inline closure keeps the existing helper unchanged.🤖 Generated with Claude Code
Note
Medium Risk
Touches core gem native rebuild path resolution; incorrect absolutization could break builds or refuse valid installs, but scope is localized to
GemCopy::ofand is covered by new unit and e2e tests.Overview
Fixes gem native-extension rebuilds when the crawl root is relative (
--cwd ., Bundler-stylevendor/bundle, or--cwd projfrom a parent).GemCopy::ofnow resolves non-rooted package paths withabsolute_lexically(dropping..like Ruby'sFile.expand_path) so spec path,GEM_PATH, and gem dirs stay absolute for Ruby runs from the project dir andextconf.rbfromext/, allowing helper gems in the same home (e.g. nokogiri-stylemini_portile2loads).Adds an ignored capstone
native_patch_builds_from_a_relative_crawl_root(helper gem + patchedextconf.rb) covering--cwd projand default in-project apply/rollback/check, plus unit testgem_copy_of_a_relative_path_is_absolute. Marker matching doc forext_dir_labelis narrowed to symlink spelling, not relative roots.Reviewed by Cursor Bugbot for commit 5b1417c. Configure here.
Generated by Claude Code