Skip to content

fix(core): leave non-regular files out of snapshot capture - #58396

Open
xzyangha wants to merge 2 commits into
anomalyco:devfrom
xzyangha:snapshot-unix-socket
Open

xzyangha wants to merge 2 commits into
anomalyco:devfrom
xzyangha:snapshot-unix-socket

Conversation

@xzyangha

@xzyangha xzyangha commented Oct 23, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #58371

Type of change

  • Bug fix

What does this PR do?

Snapshot capture aborts when the work tree contains a path that is not a regular file. Git.tree.capture lists the changed and untracked paths and hands them to git update-index --add --remove --replace, and Git refuses sockets, FIFOs and device nodes (fatal: Unable to process path …). One such path fails the whole update-index call, so the capture throws and no snapshot exists for that step.

The change stats the candidates once and leaves out the paths Git refuses, so the rest of the tree is still captured. A path that no longer exists has no stat information and is still passed through, because --remove handles deletions; directories are passed through as well, since a tracked path replaced by an embedded repository is recorded as a gitlink.

fs.stat follows links, so a symlink to a socket reports the socket's type. Git records a link itself and never opens its target, so those paths are kept: the ones with another type are only dropped when readLink shows they are not links.

This is driven by the path type rather than by which list produced it, so it covers both a tracked path that became a socket and an untracked socket that Git lists on Windows. Snapshot docs now list non-regular paths among what capture leaves out.

How did you verify your code works?

  • New cases in packages/core/test/git.test.ts: a tracked file replaced by a unix socket is left out of the tree while capture succeeds and records an unrelated edit made in the same capture; a symlink whose target is a socket is still recorded as a link (120000 blob). On dev the first fails with fatal: Unable to process path a.txt, the error from the issue.
  • bun test test/git.test.ts test/snapshot.test.ts in packages/core, plus bun run typecheck:tsc and oxlint on the changed files.

Screenshots / recordings

Not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Added by the opencode bot (AI-generated).

Related: #48657

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes the reported failure, but it introduces one regression that should be fixed before merge.

I checked it by running the new test against the base code: it fails there with fatal: Unable to process path a.txt, the error from the issue, and passes with this change. test/snapshot.test.ts passes. tsc -b for packages/core succeeds. I tested on Linux at the Git capture layer only, not on Windows, where the issue was reported.

Public API: unchanged.

The regression: fs.stat follows symlinks, so a symlink that points to a socket (for example docker.sock -> /var/run/docker.sock) is now dropped from the snapshot, though Git could record it as a link before. I confirmed this with a temporary test: the base captures link.sock and this change doesn't. Details are inline.

Related: #48657

Comment thread packages/core/src/git.ts Resolved
@xzyangha
xzyangha force-pushed the snapshot-unix-socket branch from ef20803 to 193d153 Compare October 23, 2026 08:34

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The symlink regression from my last review is fixed: paths whose type is neither file nor directory are now checked with readLink, and symlinks are kept, so a symlink to a socket is captured as a link again. The new test checks that it is stored as a link.

In packages/core, test/git.test.ts and test/snapshot.test.ts pass (29 tests), and tsc -b succeeds. The socket test fails on the base with the error from the issue and passes here. I tested on Linux only, not on Windows, where the issue was reported.

Public API: unchanged.

No new concerns.

@xzyangha

Copy link
Copy Markdown
Author

@jlongster this one is ready for a look when you have a moment.

It fixes #58371: Git.tree.capture hands every changed and untracked path to git update-index --add --remove --replace, and Git refuses sockets, FIFOs and device nodes, so a single one anywhere in the work tree aborts the whole call and that step ends up with no snapshot. The change stats the candidates once and leaves the refused paths out by type, so the rest of the tree still gets captured; symlinks are kept, since Git records the link itself without opening its target. Three files: the fix, two tests (a tracked file replaced by a unix socket; a symlink whose target is a socket), and a docs line.

The bot review found a symlink regression on the first revision and reports no new concerns on the current head. check-compliance and check-standards are green, but check / test / nix-eval have not started: this is a fork PR, so they need an "Approve and run workflows" from a maintainer first.

@xzyangha
xzyangha force-pushed the snapshot-unix-socket branch from 193d153 to 077fc11 Compare October 23, 2026 08:59

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new push leaves the code exactly as it was at my last review: the tree is identical, and only the commit was rewritten. My earlier results still apply. Symlinks are now kept, which fixes my earlier point, the tests pass, and tsc -b succeeds. I tested on Linux only, not on Windows, where the issue was reported.

Public API: unchanged.

No new concerns.

@Dextheking1 Dextheking1 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one stat driving both checks is clean. symlinks kept, the rest skipped. good.

@xzyangha

Copy link
Copy Markdown
Author

@rekram1-node could you take a look at this one when you get a chance?

It fixes #58371: Git.tree.capture hands every changed and untracked path to git update-index --add --remove --replace, and Git refuses sockets, FIFOs and device nodes, so a single one anywhere in the work tree aborts the whole call and that step ends up with no snapshot. The change stats the candidates once and leaves the refused paths out by type; symlinks are kept, since Git records the link itself without opening its target. Three files: the fix, two tests, one docs line.

The review bot reports no new concerns — it caught a symlink regression on the first revision, which is fixed in the current head. check-compliance and check-standards are green, but check, test and nix-eval are sitting in action_required: as a fork PR they need an "Approve and run workflows" from a maintainer before they start.

@xzyangha

Copy link
Copy Markdown
Author

@rekram1-node — this one still applies cleanly after #59419 and #59417: updateIndex is unchanged on current dev, so the stat-once + non-regular-file filter goes in exactly as written, and GitHub reports the branch mergeable.

Status right now: check-compliance and check-standards pass, the bot review has no new concerns (the symlink regression it caught on the first revision is fixed — symlinks are kept and covered by a test), and check / test / nix-eval are in action_required because this is a fork PR, so they need an "Approve and run workflows" before they can start.

If you'd rather have it without the docs line, or with the two socket tests merged into one, say which and I'll adjust.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

snapshot: capture fails when the work tree contains a unix socket (non-regular file)

2 participants