feat: add experimental gitoxide backend for git operations#161
Merged
feat: add experimental gitoxide backend for git operations#161
Conversation
Add gitoxide (gix crate) as a native Rust alternative to git subprocess calls, controlled by the runtime config key `daft.experimental.gitoxide`. When enabled, daft uses gitoxide for supported read-only operations (repository discovery, refs, config, status, remote queries) instead of spawning git subprocesses. All existing subprocess code remains intact as the default behavior. - Add gix dependency with blocking-network-client and status features - Create src/git_oxide.rs with implementations for 19 git operations - Add use_gitoxide field to DaftSettings, loaded from git config - Add with_gitoxide() builder on GitCommand for conditional dispatch - Propagate gitoxide flag through all command files and remote.rs - Print "[experimental] Using gitoxide backend" notice when enabled Enable with: git config daft.experimental.gitoxide true Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
gix::discover(".") stores internal paths relative to ".", causing
repo.workdir() to return "." instead of an absolute path. This broke
worktree-prune when running inside the worktree being pruned: the
relative path never matched the absolute paths from git worktree list,
so the branch was not deferred and the worktree was deleted while CWD
was still inside it.
Pass std::env::current_dir() to discover() so gix stores absolute
paths, matching subprocess git behavior.
Fixes #157
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the gix repo is discovered from a bare-repo root (as flow-eject does by changing CWD to the project root), the cached repo has no workdir. Calling repo.status() then fails with "A working tree is required to perform a directory walk". Fall back to subprocess git for has_uncommitted_changes when the cached gix repo is bare, since the subprocess correctly uses the current CWD. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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.
Summary
gixcrate) as an alternative git backend, controlled by the runtime config flagdaft.experimental.gitoxidegitsubprocessesArchitecture
GitCommandstruct gainsuse_gitoxide: boolfield andgix_repo: OnceLock<ThreadSafeRepository>for lazy repo discovery.with_gitoxide(enabled)) avoids touching existing call sitessrc/git_oxide.rsmodule (~700 lines) contains all gitoxide implementationsif self.use_gitoxide { return git_oxide::...; }std::sync::Once:[experimental] Using gitoxide backend for git operationsOperations migrated
rev_parse_git_common_dir,is_inside_git_repo,is_inside_work_tree,is_bare_repository,get_git_dir,get_current_worktree_pathsymbolic_ref_short_head,show_ref_exists,for_each_ref,branch_list_verboseconfig_get,config_get_globalhas_uncommitted_changes,rev_list_countremote_list,remote_get_urlls_remote_symref,ls_remote_heads,ls_remote_branch_existsBug fixes included
gix::discover(".")stored relative paths, causingworkdir()to return"."instead of an absolute path. Fixed by passingcurrent_dir()todiscover().repo.status()to fail. Fixed by falling back to subprocess when the cached repo is bare.Turning on the feature
git config --global daft.experimental.gitoxide trueTest plan
cargo fmt -- --checkpassescargo clippy -- -D warningspassescargo test --lib— 183 passed, 0 failedjust test-integration— default mode (gitoxide off)just test-integrationwithdaft.experimental.gitoxide=truegit worktree-prune,git worktree-flow-eject🤖 Generated with Claude Code