pub struct Repo<R: ProcessRunner = JobRunner> { /* private fields */ }Expand description
Implementations§
Source§impl<R: ProcessRunner> Repo<R>
impl<R: ProcessRunner> Repo<R>
Sourcepub fn from_git(
root: impl Into<PathBuf>,
cwd: impl Into<PathBuf>,
client: Git<R>,
) -> Self
pub fn from_git( root: impl Into<PathBuf>, cwd: impl Into<PathBuf>, client: Git<R>, ) -> Self
Build a git-backed handle from an explicit client — for a custom runner
(e.g. a test seam) or a pre-configured Git.
Sourcepub fn from_jj(
root: impl Into<PathBuf>,
cwd: impl Into<PathBuf>,
client: Jj<R>,
) -> Self
pub fn from_jj( root: impl Into<PathBuf>, cwd: impl Into<PathBuf>, client: Jj<R>, ) -> Self
Build a jj-backed handle from an explicit client.
Sourcepub fn kind(&self) -> BackendKind
pub fn kind(&self) -> BackendKind
Which backend drives this handle.
Sourcepub fn at(&self, dir: impl Into<PathBuf>) -> Self
pub fn at(&self, dir: impl Into<PathBuf>) -> Self
A sibling handle bound to dir, sharing this handle’s client and root.
Sourcepub fn git(&self) -> Option<&Git<R>>
pub fn git(&self) -> Option<&Git<R>>
The underlying Git client, or None when jj-backed — an escape hatch
to git-only operations not on the common surface.
Sourcepub fn git_at(&self) -> Option<GitAt<'_, R>>
pub fn git_at(&self) -> Option<GitAt<'_, R>>
The git client bound to this handle’s cwd — a GitAt whose
methods omit the dir argument — or None when jj-backed. The dir-free
counterpart of git: repo.git_at()?.merge_continue().await?.
The returned view borrows self. To work in another worktree, bind the
re-anchored handle first (the view can’t outlive a temporary
at):
let wt = repo.at(wt); // owns the re-anchored handle
let git = wt.git_at().unwrap();
git.fetch().await?;Sourcepub async fn current_branch(&self) -> Result<Option<String>>
pub async fn current_branch(&self) -> Result<Option<String>>
The current branch (git) or bookmark (jj); None when detached / no
bookmark on the working copy.
Sourcepub async fn trunk(&self) -> Result<Option<String>>
pub async fn trunk(&self) -> Result<Option<String>>
The trunk branch/bookmark. Resolution order: the backend’s own notion
(git’s origin/HEAD, jj’s trunk() revset), then a fallback to a local
main, then master; None when none of those resolve.
Sourcepub async fn local_branches(&self) -> Result<Vec<String>>
pub async fn local_branches(&self) -> Result<Vec<String>>
Local branch (git) / bookmark (jj) names.
Sourcepub async fn branch_exists(&self, name: &str) -> Result<bool>
pub async fn branch_exists(&self, name: &str) -> Result<bool>
Whether a local branch/bookmark named name exists.
Sourcepub async fn has_uncommitted_changes(&self) -> Result<bool>
pub async fn has_uncommitted_changes(&self) -> Result<bool>
Whether the working copy has uncommitted changes (git: a non-empty
status; jj: a non-empty working-copy change @).
Sourcepub async fn delete_branch(&self, name: &str, force: bool) -> Result<()>
pub async fn delete_branch(&self, name: &str, force: bool) -> Result<()>
Delete a local branch (git) / bookmark (jj). force applies to git only
(branch -D vs -d); jj has no force and ignores it.
Sourcepub async fn rename_branch(&self, old: &str, new: &str) -> Result<()>
pub async fn rename_branch(&self, old: &str, new: &str) -> Result<()>
Rename a local branch (git) / bookmark (jj).
Sourcepub async fn changed_files(&self) -> Result<Vec<FileChange>>
pub async fn changed_files(&self) -> Result<Vec<FileChange>>
The working-copy changes (git status / jj diff -r @ --summary).
Sourcepub async fn diff_stat(&self) -> Result<DiffStat>
pub async fn diff_stat(&self) -> Result<DiffStat>
Aggregate insertion/deletion counts for the working copy.
Backend nuance: git counts the working tree against HEAD (git diff,
which excludes untracked files), while jj counts the @ change against
its parent (which includes newly-added files). So on git a brand-new
file shows in changed_files but not here, whereas
on jj it shows in both.
Sourcepub async fn commit_paths(&self, paths: &[String], message: &str) -> Result<()>
pub async fn commit_paths(&self, paths: &[String], message: &str) -> Result<()>
Commit exactly paths with message (git commit --only, jj
commit <filesets>). Paths are repo-relative.
Sourcepub async fn fetch(&self) -> Result<()>
pub async fn fetch(&self) -> Result<()>
Fetch from the default remote (git fetch / jj git fetch).
Sourcepub async fn fetch_remote_branch(&self, branch: &str) -> Result<()>
pub async fn fetch_remote_branch(&self, branch: &str) -> Result<()>
Fetch a single branch/bookmark from origin into its remote-tracking ref
(git fetch_remote_branch / jj git fetch -b). Transient network failures
are retried by the underlying client.
Sourcepub async fn checkout(&self, reference: &str) -> Result<()>
pub async fn checkout(&self, reference: &str) -> Result<()>
Switch the working copy to reference (git checkout / jj edit).
Sourcepub async fn rebase(&self, onto: &str) -> Result<()>
pub async fn rebase(&self, onto: &str) -> Result<()>
Rebase the current work onto onto (git rebase / jj rebase -d). The
onto is a branch/bookmark name or revision the backend understands.
Sourcepub async fn in_progress_state(&self) -> Result<OperationState>
pub async fn in_progress_state(&self) -> Result<OperationState>
Whether the working copy is mid-operation or conflicted — see
OperationState. Lets a caller decide between abort/continue without
knowing the backend’s model. Note the asymmetry: git reports Merge/
Rebase (a git conflict is that paused state — the conflict itself
surfaces on the failed op via Error::is_conflict), while jj has no
paused op and reports Conflict directly.
Sourcepub async fn list_worktrees(&self) -> Result<Vec<WorktreeInfo>>
pub async fn list_worktrees(&self) -> Result<Vec<WorktreeInfo>>
List attached worktrees (git) / workspaces (jj).
Sourcepub async fn create_worktree(
&self,
path: &Path,
branch: &str,
base: &str,
) -> Result<CreateOutcome>
pub async fn create_worktree( &self, path: &Path, branch: &str, base: &str, ) -> Result<CreateOutcome>
Create a worktree/workspace at path on a new branch based on
base. Always CreateOutcome::Plain; a copy-on-write strategy stays in
the consumer.
branch must not already exist. The jj path is two steps (workspace add
then bookmark create) and is not atomic: if the bookmark step fails, the
freshly-added workspace is left in place for the caller to clean up. A
consumer needing resume-existing or rollback semantics should drive the
underlying client via jj / git.
Sourcepub async fn remove_worktree(&self, path: &Path, force: bool) -> Result<()>
pub async fn remove_worktree(&self, path: &Path, force: bool) -> Result<()>
Remove the worktree/workspace at path. For jj this resolves the
workspace name by matching path, deletes the directory, then forgets it.
Sourcepub fn cleanup_worktree_blocking(&self, path: &Path) -> Result<()>
pub fn cleanup_worktree_blocking(&self, path: &Path) -> Result<()>
Synchronous worktree cleanup for a context that cannot .await —
chiefly a Drop guard. Force-removes the worktree at path (git:
worktree remove --force; jj: resolve the workspace name by path, delete
the directory, then workspace forget). Best-effort and short-lived: it
shells out directly (no job-containment); a jj path that matches no
workspace is a no-op (Ok).
Trait Implementations§
Source§impl<R: ProcessRunner> VcsRepo for Repo<R>
impl<R: ProcessRunner> VcsRepo for Repo<R>
Source§fn kind(&self) -> BackendKind
fn kind(&self) -> BackendKind
Source§fn current_branch<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn current_branch<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Repo::current_branch.Source§fn trunk<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn trunk<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Repo::trunk.Source§fn local_branches<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn local_branches<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Repo::local_branches.Source§fn branch_exists<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn branch_exists<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Repo::branch_exists.Source§fn has_uncommitted_changes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn has_uncommitted_changes<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn delete_branch<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
force: bool,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn delete_branch<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
force: bool,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Repo::delete_branch.Source§fn rename_branch<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
old: &'life1 str,
new: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn rename_branch<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
old: &'life1 str,
new: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Repo::rename_branch.Source§fn changed_files<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<FileChange>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn changed_files<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<FileChange>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Repo::changed_files.Source§fn diff_stat<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<DiffStat>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn diff_stat<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<DiffStat>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Repo::diff_stat.Source§fn commit_paths<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
paths: &'life1 [String],
message: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn commit_paths<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
paths: &'life1 [String],
message: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Repo::commit_paths.Source§fn fetch<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn fetch<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Repo::fetch.Source§fn fetch_remote_branch<'life0, 'life1, 'async_trait>(
&'life0 self,
branch: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn fetch_remote_branch<'life0, 'life1, 'async_trait>(
&'life0 self,
branch: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn checkout<'life0, 'life1, 'async_trait>(
&'life0 self,
reference: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn checkout<'life0, 'life1, 'async_trait>(
&'life0 self,
reference: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Repo::checkout.Source§fn rebase<'life0, 'life1, 'async_trait>(
&'life0 self,
onto: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn rebase<'life0, 'life1, 'async_trait>(
&'life0 self,
onto: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Repo::rebase.Source§fn in_progress_state<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<OperationState>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn in_progress_state<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<OperationState>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn list_worktrees<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<WorktreeInfo>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_worktrees<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<WorktreeInfo>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Repo::list_worktrees.