Skip to content

fix(gix-index): correctly decode untracked extension#2591

Merged
Sebastian Thiel (Byron) merged 6 commits into
GitoxideLabs:mainfrom
AaronMoat:untracked-extension-reading
May 12, 2026
Merged

fix(gix-index): correctly decode untracked extension#2591
Sebastian Thiel (Byron) merged 6 commits into
GitoxideLabs:mainfrom
AaronMoat:untracked-extension-reading

Conversation

@AaronMoat
Copy link
Copy Markdown
Contributor

  • Fix ctime/mtime flip in stat decoding
  • Fix incomplete decoding to mirror git, with associated ported git test

Split out from #2503 as requested. I thought including the untracked cache parsing end-to-end was small enough and more logical than just the ctime/mtime flip -- as that's the only spot it's used anyway. Hope that's okay.

The tests added are limited; most of git's tests are focused on its interactions with git status. The tests added are attempting to replicate these.

As for the ctime/mtime Sebastian Thiel (@Byron):

Can we land this separately? Ideally with a test if that's possible. I remember that some strange swapping was going on when decoding, but I always thought it was necessary. Maybe I got it wrong and no test caught it. Let's take a separate look.

I'm not really sure what we should test: I don't see an obvious git test to port. As for correctness, it seems that the data is just read into this struct, which is ctime then mtime. The existing code was reading ctime then mtime variables correctly, then assigning the reverse into the rust struct.

Let me know if there's any test suggestions, happy to extend them. I don't know the git source code very well so may very well be missing some good tests there.

@AaronMoat Aaron Moat (AaronMoat) force-pushed the untracked-extension-reading branch 2 times, most recently from 6253514 to 85643fa Compare May 9, 2026 14:03
@AaronMoat Aaron Moat (AaronMoat) marked this pull request as ready for review May 9, 2026 15:01
- Fix ctime/mtime flip in stat decoding
- Fix incomplete decoding to mirror git, with associated ported git test

Co-authored-by: GPT 5.4 <codex@openai.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@Byron
Copy link
Copy Markdown
Member

Sebastian Thiel (Byron) commented May 12, 2026

Tasks

  • review - double-check
  • split gix-testtools feature out into own commit
  • add XDG_CONFIG_HOME override

@Byron Sebastian Thiel (Byron) force-pushed the untracked-extension-reading branch from 0e4bd3c to 954c5c8 Compare May 12, 2026 11:32
Codex (codex) and others added 3 commits May 12, 2026 19:39
Add `scripted_fixture_read_only_needs_archive()` for fixtures whose generated
output can vary in byte order across platforms or filesystems. The helper
still validates archive identity, but bypasses GIX_TEST_IGNORE_ARCHIVES and
re-extracts the checked-in archive so tests can opt into frozen fixture bytes
when rerunning the producer is non-deterministic,
for instance due to filesystem order.

Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes gix-index’s decoding of the index UNTR (untracked cache) extension to match Git’s on-disk layout, and corrects a ctime/mtime swap in stat decoding. It also adds fixtures + snapshot-style tests to validate end-to-end decoding of the untracked cache directory graph.

Changes:

  • Fix decode::stat() to assign decoded ctime/mtime to the correct entry::Stat fields.
  • Adjust UNTR decoding to read both stats, then dir_flags, then both hashes (matching Git), and add public accessors + Debug derives for snapshotting.
  • Add new archived fixtures + tests for empty/populated/nested untracked cache decoding; update testtools to support “must use archive” fixtures and isolate XDG_CONFIG_HOME.

Reviewed changes

Copilot reviewed 11 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/tools/src/tests.rs Adds a test to ensure configure_command() overrides XDG_CONFIG_HOME.
tests/tools/src/lib.rs Adds “needs archive” fixture helper; ensures fixture commands run with a private XDG_CONFIG_HOME; threads needs_archive through archive extraction.
gix-index/tests/index/main.rs Adds a fixture helper that forces using archived fixtures even when archives are otherwise ignored.
gix-index/tests/index/file/read.rs Adds snapshot tests (via insta) for decoded UNTR extension shapes (empty/populated/nested) using archived fixtures.
gix-index/tests/fixtures/make_index/untracked_cache_empty.sh New fixture generator for an index with an empty UNTR cache.
gix-index/tests/fixtures/make_index/untracked_cache_populated.sh New fixture generator producing a populated UNTR cache via git status.
gix-index/tests/fixtures/make_index/untracked_cache_nested.sh New fixture generator covering nested directories and per-dir ignore OIDs in UNTR.
gix-index/src/extension/untracked_cache.rs Implements Git-aligned UNTR decode layout; adds Debug derives and accessor methods for snapshot-friendly inspection.
gix-index/src/extension/mod.rs Derives Debug for UntrackedCache.
gix-index/src/decode/mod.rs Fixes ctime/mtime field assignment in stat decoding.
gix-index/Cargo.toml Adds insta as a dev-dependency for new snapshot tests.
Cargo.lock Locks new dev-dependency additions (e.g., insta/transitives).

Comment thread tests/tools/src/tests.rs
Comment thread gix-index/src/decode/mod.rs
Seed the untracked-cache fixture paths with a known mtime before Git
populates the UNTR extension. Keeping that mtime visible in the snapshot
covers the ctime/mtime decode ordering: if the fields are swapped, the
expectation will show the unexpected timestamp.

Leave ctime redacted because it is filesystem metadata-change time and
varies by platform and run, while still preserving enough snapshot detail
to catch the decode-order regression.

Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 18 changed files in this pull request and generated 2 comments.

Comment thread tests/tools/src/tests.rs
Comment thread gix-index/tests/fixtures/make_index/shared.sh
@Byron Sebastian Thiel (Byron) force-pushed the untracked-extension-reading branch 2 times, most recently from 2196d82 to e8de738 Compare May 12, 2026 14:09
This allows tests to rely on it more with insta, and not miss a thing.

Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
@Byron Sebastian Thiel (Byron) force-pushed the untracked-extension-reading branch from e8de738 to e4bdd1f Compare May 12, 2026 14:09
@Byron Sebastian Thiel (Byron) merged commit 85c6087 into GitoxideLabs:main May 12, 2026
32 checks passed
@Byron
Copy link
Copy Markdown
Member

Just as an FYI for Eliah Kagan (@EliahKagan), This pr also adds an extension to gix-testtools which allows to force the usage of an archive. This is useful if some data created by the underlying shell script is inherently unstable and not under our control.
Overall, I think that's a better system than the one I used previously, which is to copy the artifacts into the fixture directory and track them without any indication of how they were created or where they are from.

@Byron
Copy link
Copy Markdown
Member

Oh, and now that I see it: Thanks a lot for making this happen Aaron Moat (@AaronMoat), it's much appreciated!
I didn't want to seem ungrateful. I just forgot to write this message yesterday after a long day spent with this PR.

It's interesting that in the age of agentic, you don't necessarily need less time to get into something, because you're still the puny human you were before, but instead you get more done in that time as you can just instruct the agent to do it real quick. While I look, play, investigate, watch and learn, there's always an agent doing work for me. And that then has to be reviewed again, so there's more work and more work being created on the fly, which just didn't happen before 😁.
But also that work represents value and overall the project project moves much faster than it could otherwise, as any barriers (like "nah, this seems difficult and there are too many unknowns to tackle this") are now gone.

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.

4 participants