Repository navigation
Fix stray files breaking vendored Gradle (#656) - #1819
Mikola Lysenko (mikolalysenko) merged 8 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
A file the index does not list in a vendored Gradle or Maven tree, such as a Finder .DS_Store, fails the Gradle build and vendor --check. The build error says to re-run `socket-patch vendor`, but vendor compared only the files it plans to write, reported already_vendored and left the stray file in place, and repair did nothing either. vendor now treats anything unindexed in its tree directories as drift: a dry run previews a re-vendor and a real run deletes the strays. repair deletes them offline for a healthy JVM entry and reports the package as rebuilt. Fixes #656 Assisted-by: Claude Code:claude-opus-5-5
Adds a real Gradle e2e for #656: a .DS_Store in the vendored tree fails the build, and both `vendor` and `repair` restore a build that consumes the patched jar. repair now only trusts tree records inside the entry's own version directory, so a forged ledger marker cannot point the sweep at another artifact's files. Assisted-by: Claude Code:claude-opus-5-5
Review fixes for the #656 sweep: - vendor deletes stray tree entries before writing any wiring, and deletes them directly instead of through the run's group commit, which would read a stray symlink back through its target and fail the whole commit. - A directory that cannot be deleted is now an error instead of a silent success; an entry already gone counts as removed. - vendor --check and the sweep share one lister, so they agree on what is unindexed. - repair --dry-run previews the files it would remove (wouldRemoveUnindexed), and a real repair lists them. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
|
BugBot review Generated by Claude Code |
If a vendored version directory, or a parent of it, is a symlink to another place in the checkout, its "stray" entries may be another artifact's files. vendor and repair now refuse to delete them and name the path, while vendor --check still reports them as unindexed. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
vendor --dry-run and repair --dry-run now fail the same way as a real run when a vendored tree directory is reached through a symlink, instead of previewing a sweep that the real run then refuses. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
|
Burn-down agent: labeled Ready for review at
Generated by Claude Code |
Final review briefWhat it does. Risk: low-medium. It deletes files, but only inside Look here
Verified.
Changes I made. None. Open questions (non-blocking; follow-ups if you care):
Auto-merge is armed, so approving sends it straight to the merge queue. Generated by Claude Code |
On Windows a directory symlink or junction can't be removed with remove_file, so a stray one in a vendored tree made vendor and repair fail. It is now unlinked with remove_dir, which leaves its target alone. Also fixes a stale test comment about the group commit. Assisted-by: Claude Code:claude-opus-5-5
|
[agent] On the final review brief's open questions:
Generated by Claude Code |
|
BugBot review Generated by Claude Code |
vendor removed stray files from the vendored tree before writing anything else, and judged them against the new plan only. A file the committed ledger still recorded, such as a classifier jar the build no longer declares, was deleted there. If the write was then refused or rolled back, the restored ledger and gradle-index.tsv named a file that was gone. Recorded files are no longer strays; a patch update's dropped files are still removed after the commit, as on main. Assisted-by: Claude Code:claude-opus-5-5
|
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 6292d2a. Configure here.
Final review briefWhat it does. A file a vendored JVM tree's index doesn't list ( Risk: medium. The change deletes files inside Look here
Verified. Read the full diff and the PR description, which matches the code. CI is green on Changes I made. None. Open questions. None blocking. Design choice for the approver: a stray directory in the tree is deleted recursively, on the basis that only socket-patch's files belong there. Auto-merge is armed, so approving sends this straight to the merge queue. Generated by Claude Code |
|
Burn-down agent: Ready for review confirmed at
Generated by Claude Code |
|
[agent] Dequeued by a CI infrastructure failure, not by this PR's code. In merge-group CI run 40947334054, The PR's own CI is green on Generated by Claude Code |
|
[agent] Dequeued again by the same Depot runner loss. In merge-group CI run 40950997135, 9 jobs failed with zero steps recorded after 600–1100 s, each on a different Depot runner: It needs another re-queue once the Depot runners recover (see #1660). No code change is needed. Generated by Claude Code |
|
CI janitor: both merge-queue evictions of this PR today (20:29 and 21:03 UTC) came from Depot runners losing contact mid-job ("self-hosted runner lost communication"), not from this PR's code. Evidence is on #1660. This PR was evicted twice in 24h, so I am not re-adding it. Re-queue it once Depot is stable again. Generated by Claude Code |
|
CI janitor: this PR was evicted from the merge queue twice today. Both times the cause was Depot runner loss, not this PR's code.
The PR is still approved, green on its head and clean. I'm not re-queuing it a third time while the Depot incident (#1660) continues. The final-review routine can re-add it once runners are healthy again. Generated by Claude Code |
|
Both merge-queue evictions today (merge_group runs 40947334054 and 40950997135) were caused by Depot runners losing connection, not by this PR: every failed job has the Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Fixes #656
Summary
A file in a vendored JVM tree that its index doesn't list (a Finder
.DS_Store,Thumbs.db, an editor backup, a stray directory) fails every Gradle build with "unindexed files … re-runsocket-patch vendor". Before this PR, that remedy did nothing:vendorreportedalready_vendored,repairchanged nothing, and onlyvendor --checksaw the problem.Now:
vendortreats unindexed entries in its tree directories as drift.--dry-runpreviews a re-vendor (statusready, notalready_vendored). A real run deletes the strays before it writes any wiring, then re-vendors. A stray symlink is deleted, not its target. A stray directory is deleted with its contents, since only socket-patch's files belong in the tree.repairdeletes them offline for a healthy JVM entry and recordsrebuiltwithunindexedRemoved: [paths].repair --dry-runrecordsverifiedwithwouldRemoveUnindexed: [paths]and writes nothing.vendor --check(check_entry) and the sweep share one lister (jvm::apply::unindexed_in), so they agree on what counts as unindexed.Covers the Gradle tree (the reported case), the Maven reactor tree, and a mixed root's two trees.
Root cause
vendor_maven_jvmdecides "in sync" fromplan.writes.is_empty(), which compares only the files the plan would write. It never listed the tree directories, so an extra file was invisible tovendor/repair.check_entryand the Gradle settings script both list them and reject extras.Safety notes
/code-review high).repairreads tree records from the committed ledger, which can be tampered with. It only uses records thatrecord_allowedaccepts for the entry's own coordinates, so a forged marker can't point the sweep at another artifact's directory (unit test).sweep_replaced_tree, as on main (jvm_rerun_keeps_tree_files_the_ledger_records, from a human review).remove_dir, so its target is left alone (from the final review brief).vendor --checkuntil re-vendored.Tests (red → green)
vendor/--dry-runsayalready_vendoredover a stray (reactor + Gradle)vendor::maven_repo::tests::jvm_rerun_sweeps_unindexed_tree_filesAlreadyPatchedvendor,vendor --check,repair,repair --dry-run, stray symlink under the group commit (reactor + Gradle)vendor_jvm_cli::stray_tree_files_are_swept_by_vendor_and_repair"errorCode":"already_vendored"vendorand afterrepaire2e_vendor_gradle_build::gradle_vendor_656_stray_tree_file(--ignored, Gradle 8.14.3 locally; runs in thegradle_vendor_CI legs)vendor::jvm::apply::tests::sweep_unindexed_removes_only_strays_in_the_own_treevendor::jvm::apply::tests::sweep_unindexed_refuses_a_linked_tree_dirCommands run locally:
cargo fmt --all -- --check: cleancargo clippy --workspace --all-features -- -D warnings: cleancargo test -p socket-patch-core --all-features --lib: 6925 pass, 4 fail. All 4 (copy_tree::relax_loop_must_not_traverse_symlinked_root,vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry,pypi_poetry::wire_write_failure_…,pypi_requirements::wire_failure_rolls_back_…) are permission-denial tests that can't fail a write when run as root in this sandbox. None touch JVM code.cargo test -p socket-patch-cli --all-features --test vendor_jvm_cli: 53/53 pass--test repair: 127 pass, 2 fail (repair_cleanup_failure_…,…_lock_file_unremovable), same root-only causecargo test --workspaceran out of sandbox disk while linking test binaries, so CI is the full-suite gate./code-review high findings not changed
write_planordering concern is fixed: ledger-recorded files are excluded from the stray sweep.)redownload::restore, whoseswap_stage_into_placereplaces the whole tree directory (and a mixed root's other tree), so strays don't survive it.vexstill attestsnot_affectedwhile a stray file makes the build fail. That failure is fail-closed (no unpatched jar is built), and the stray is now cleared by the remedy the error names, so this PR leaves it.https://claude.ai/code/session_011f9aePVZMMe2T6XR46RuNb
Generated by Claude Code