Skip to main content

Repo

Struct Repo 

Source
pub struct Repo<R: ProcessRunner = JobRunner> { /* private fields */ }
Expand description

A cwd-bound, backend-agnostic VCS handle. Operations run against the bound directory (cwd); use at to get a sibling handle bound elsewhere.

Implementations§

Source§

impl Repo<JobRunner>

Source

pub fn open(dir: impl AsRef<Path>) -> Result<Self>

Detect the repository at or above dir and open a handle bound to dir, using the real job-backed runner. Errors with Error::NotARepository when no .git/.jj is found.

Source§

impl<R: ProcessRunner> Repo<R>

Source

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.

Source

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.

Source

pub fn kind(&self) -> BackendKind

Which backend drives this handle.

Source

pub fn root(&self) -> &Path

The repository root detected at open time.

Source

pub fn cwd(&self) -> &Path

The directory operations run against.

Source

pub fn at(&self, dir: impl Into<PathBuf>) -> Self

A sibling handle bound to dir, sharing this handle’s client and root.

Source

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.

Source

pub fn jj(&self) -> Option<&Jj<R>>

The underlying Jj client, or None when git-backed.

Source

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?;
Source

pub fn jj_at(&self) -> Option<JjAt<'_, R>>

The jj client bound to this handle’s cwd — a JjAt whose methods omit the dir argument — or None when git-backed. The dir-free counterpart of jj. For another workspace, bind the re-anchored handle first (let ws = repo.at(path); ws.jj_at()…) — see git_at.

Source

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.

Source

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.

Source

pub async fn local_branches(&self) -> Result<Vec<String>>

Local branch (git) / bookmark (jj) names.

Source

pub async fn branch_exists(&self, name: &str) -> Result<bool>

Whether a local branch/bookmark named name exists.

Source

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 @).

Source

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.

Source

pub async fn rename_branch(&self, old: &str, new: &str) -> Result<()>

Rename a local branch (git) / bookmark (jj).

Source

pub async fn changed_files(&self) -> Result<Vec<FileChange>>

The working-copy changes (git status / jj diff -r @ --summary).

Source

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.

Source

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.

Source

pub async fn fetch(&self) -> Result<()>

Fetch from the default remote (git fetch / jj git fetch).

Source

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.

Source

pub async fn checkout(&self, reference: &str) -> Result<()>

Switch the working copy to reference (git checkout / jj edit).

Source

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.

Source

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.

Source

pub async fn list_worktrees(&self) -> Result<Vec<WorktreeInfo>>

List attached worktrees (git) / workspaces (jj).

Source

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.

Source

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.

Source

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>

Source§

fn kind(&self) -> BackendKind

Which backend drives this handle.
Source§

fn root(&self) -> &Path

The repository root detected at open time.
Source§

fn cwd(&self) -> &Path

The directory operations run against.
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,

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,

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,

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,

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,

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,

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,

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,

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,

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,

Source§

fn fetch<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

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,

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,

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,

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,

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,

Source§

fn create_worktree<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, path: &'life1 Path, branch: &'life2 str, base: &'life3 str, ) -> Pin<Box<dyn Future<Output = Result<CreateOutcome>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Source§

fn remove_worktree<'life0, 'life1, 'async_trait>( &'life0 self, path: &'life1 Path, force: bool, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn cleanup_worktree_blocking(&self, path: &Path) -> Result<()>

Auto Trait Implementations§

§

impl<R> Freeze for Repo<R>

§

impl<R> RefUnwindSafe for Repo<R>
where R: RefUnwindSafe,

§

impl<R> Send for Repo<R>

§

impl<R> Sync for Repo<R>

§

impl<R> Unpin for Repo<R>

§

impl<R> UnsafeUnpin for Repo<R>

§

impl<R> UnwindSafe for Repo<R>
where R: RefUnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.