What Is the Role of the Repository Struct in Worktrunk's Git Core?
The Repository struct serves as the central abstraction in Worktrunk's Git core, encapsulating repository discovery, shared caching, and thread-safe coordination for all worktree operations.
Worktrunk is a Rust-based CLI tool designed for efficient Git worktree management. At the heart of its architecture lies the Repository struct, defined in src/git/repository/mod.rs, which provides a unified interface for discovering, caching, and coordinating access to Git repositories.
Central Representation and Discovery
The Repository struct acts as the canonical representation of a Git repository within Worktrunk's type system. It stores two critical path fields that distinguish between the entry point and the actual Git metadata location.
According to the source code at src/git/repository/mod.rs (lines 67-74), the struct definition includes:
pub struct Repository {
discovery_path: PathBuf,
git_common_dir: PathBuf,
// ...
}
The discovery_path represents the path used to initially locate the repository, while the git_common_dir points to the actual .git directory (or the bare repository equivalent). This separation allows Worktrunk to handle complex repository layouts, including worktrees and alternate object databases, while maintaining a consistent reference to the repository's core metadata.
Shared State and Caching Architecture
Performance in Worktrunk relies on aggressive caching orchestrated through the Repository struct. Each instance maintains shared state via an Arc<RepoCache>, ensuring that expensive Git operations are executed only once per process.
As implemented in src/git/repository/mod.rs (lines 75-78), all repository-wide information—including default branch detection, configuration values, and branch inventories—is stored in this cache. When you clone a Repository value, you reuse the same cache rather than re-reading from disk.
Worktrunk implements three distinct caching layers:
-
RepoCache(per-instance) – Shared viaArcacross clonedRepositoryinstances, storing repo-wide values like merge-base results and branch inventories to avoid duplicate Git commands during a single CLI invocation. -
Process-wide statics – Global
LazyLockandOnceLockstructures (such asWORKTREE_ROOTS,GIT_DIRS, andGIT_CONFIG_PRELOAD) that persist across allRepositoryobjects created in the process, ensuring cold-path discovery costs are paid only once. -
On-disk
sha_cache– JSON files under.git/wt/cache/that persist expensive, repeatable results (like merge-tree outcomes) across process invocations.
The design guarantees cache immutability within a single command execution, eliminating race conditions during parallel worktree processing.
Thread-Safe Worktree Coordination
Concurrent modification of worktree metadata requires careful synchronization. The Repository struct attaches a global lock to each repository's common-git directory to serialize operations that modify the worktree registry.
As defined at src/git/repository/mod.rs (lines 85-88), the WORKTREE_REGISTRY_LOCKS mechanism ensures that adding or removing worktrees is serialized across all Repository instances pointing to the same underlying repository. This prevents corruption when multiple threads or processes manipulate worktree metadata simultaneously.
Factory Methods and Construction
Worktrunk centralizes Repository creation through two primary constructors that ensure consistent initialization of caches and locks.
Repository::current() (lines 16-20) provides a convenience wrapper that creates a Repository from the global base path (specified via the -C flag) or the current working directory:
let repo = Repository::current()?;
Repository::at(path) (lines 30-44) serves as the core constructor. This method resolves the Git common directory, installs the worktree registry lock, and optionally integrates pre-loaded configuration caches populated during the pre-warm phase:
let repo = Repository::at(PathBuf::from("/path/to/repo"))?;
Both methods ensure every Repository instance inherits the same cache layout and synchronization semantics.
Worktree-Specific Operations
While Repository handles repo-wide concerns, concrete worktree manipulation occurs through the WorkingTree type. The repository acts as an entry point for spawning per-worktree objects that inherit the shared cache.
As shown at src/git/repository/mod.rs (lines 49-57), you obtain a WorkingTree from a Repository instance:
let repo = Repository::current()?;
let wt = repo.current_worktree(); // Returns worktree-specific API
This architecture separates global queries (default branch, configuration) from worktree-local operations (file status, branch checkout), while both layers benefit from the same underlying cache.
Observation Mode and Temporary Object Stores
For read-only commands such as wt list, Worktrunk redirects Git's object writes to a temporary object database to prevent modifying the repository state. The Repository struct manages this through a temporary object store mechanism.
Implemented at src/git/repository/mod.rs (lines 84-99), this feature:
- Creates a temporary directory (
temporary_object_store) - Registers the path in
observation_object_directoriesto prevent worktree logic from interpreting it as a real worktree - Adjusts Git command environments via
with_object_store_env
The temporary store persists as long as any cloned Repository carries the reference, ensuring automatic cleanup when the last clone drops.
Pre-warming for Cold-Path Optimization
To minimize latency during initial operations, Repository provides a prewarm() method that populates process-wide caches before any repository queries occur.
As implemented at src/git/repository/mod.rs (lines 160-188), Repository::prewarm() launches three background threads that:
- Resolve the common-git directory via
git rev-parse - Load the entire Git configuration via
git config --list -z - Parse the user-level Worktrunk configuration from
wt.toml
These results populate the process-wide static caches, allowing the first real Repository instantiation to retrieve them without spawning additional subprocesses.
Summary
- The Repository struct centralizes Git repository discovery, storing both the discovery path and resolved
.gitdirectory location insrc/git/repository/mod.rs. - It orchestrates a three-tier caching strategy—per-instance
RepoCache, process-wide statics, and on-disk SHA caches—to minimize Git subprocess overhead. - Thread safety for worktree registry modifications is guaranteed through the
WORKTREE_REGISTRY_LOCKSmechanism attached to each repository instance. - Factory methods
Repository::current()andRepository::at()ensure consistent initialization of caches and locks across all code paths. - The struct provides the entry point for worktree-specific operations via the
current_worktree()method, returning aWorkingTreeobject that shares the underlying cache. - Observation mode support allows read-only commands to operate safely using temporary object stores that automatically clean up when the
Repositoryis dropped.
Frequently Asked Questions
What fields does the Repository struct contain?
The Repository struct contains discovery_path and git_common_dir fields of type PathBuf, along with shared cache and lock handles. The discovery path represents where the repository was found, while the git_common_dir points to the actual .git metadata directory, enabling support for worktrees and alternate object stores.
How does the Repository struct handle caching?
The struct uses an Arc<RepoCache> to share repository-wide data across cloned instances, combined with process-wide static caches (LazyLock and OnceLock globals) and persistent on-disk JSON caches under .git/wt/cache/. This three-layer approach ensures expensive Git operations execute only once per process or persist across invocations.
What is the difference between Repository and WorkingTree?
Repository represents the Git repository itself and handles repo-wide concerns like configuration, default branch detection, and the worktree registry. WorkingTree represents a specific worktree checkout and handles file-level operations. You obtain a WorkingTree by calling repo.current_worktree() on a Repository instance, inheriting the parent's shared cache.
How does Repository ensure thread safety?
Thread safety is achieved through the WORKTREE_REGISTRY_LOCKS global lock map, which assigns a unique lock to each repository's common-git directory. This ensures that operations modifying the worktree registry—such as adding or removing worktrees—are serialized across all Repository instances pointing to the same underlying repository, preventing metadata corruption during concurrent access.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →