Repository navigation
tecnix: read staged-only dirty paths from the git index - #75
Open
GoodForOneFare wants to merge 1 commit into
Open
GoodForOneFare wants to merge 1 commit into
GoodForOneFare wants to merge 1 commit into
Conversation
GoodForOneFare
force-pushed
the
gordo-fix-staged-only-index-overlay
branch
5 times, most recently
from
October 6, 2026 11:44
13a65c8 to
fcf29ae
Compare
The repo accessor sends every path `git status` reports to the working tree. During an uncommitted merge (or cherry-pick, revert, rebase stop) in a sparse checkout, git stages the cleanly merged files outside the sparse set but never writes them: they are skip-worktree entries whose only copy is the index blob. Evaluation then fails on the first one it reads with `path '«unknown»/<file>' does not exist`, and only committing the operation clears it. In World this reaches `tec build :__devEnv` in any sparse worktree that merges main without committing. Parse `git status --porcelain=v2 -z` instead of v1, keeping each entry's status and index blob. An ordinary or renamed entry whose worktree column is `.` has no change of its own against the index, so its content is that blob: serve readFile, readLink, lstat, directory listing and the dirty fingerprint for those paths from the index through the GitRepo the accessor already holds. For a materialized file the bytes are the same as on disk, so fingerprints are unchanged. Worktree-modified, unmerged, untracked and deleted entries stay on disk, as do all dirty paths in worldtree sandboxes, which have no libgit2 repository to read blobs from. Co-authored-by: Gord Pearson <gord.pearson@shopify.com>
GoodForOneFare
force-pushed
the
gordo-fix-staged-only-index-overlay
branch
from
October 6, 2026 12:13
fcf29ae to
d10f40c
Compare
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.
Motivation
Fixes
dev upin World failing with tec build errors likepath '«unknown»/system/tectonix/modules/dev.nix' does not exist. It happens when a sparse checkout is mid-operation: most often an uncommitted merge of main (e.g. one stopped on a conflict), but also a stopped cherry-pick, revert or rebase. Agents in secondary worktrees hit it most, because they merge main and leave the merge uncommitted.Context
The repo accessor sends every path
git statusreports to the working tree. During an uncommitted merge in a sparse checkout, git stages the cleanly merged files outside the sparse set but never writes them: they are skip-worktree entries whose only copy is the index blob. Evaluation then fails on the first one it reads, and only committing the operation clears it.Changes
git status --porcelain=v2 -zinstead of v1, keeping each entry's status and index blob. Both names of a rename are dirty; the source of a copy is not (classified by the score field, soC.and.Calike). Unmerged and untracked paths are dirty as before.., and whose index entry is a regular file, executable or symlink, has no change of its own against the index, so its content is that blob. readFile, readLink, lstat, directory listings and the dirty fingerprint for those paths are served from the index through the GitRepo the accessor already holds.readDirwith "not a directory", as the committed tree does, instead of listing nothing. That last case was also wrong in fully materialized checkouts.