Skip to main content

WorktreeService

Struct WorktreeService 

Source
pub struct WorktreeService { /* private fields */ }
Expand description

The repository’s worktrees, decided once.

Built from a directory — any directory inside any work tree — and nothing else.

Implementations§

Source§

impl WorktreeService

Source

pub fn open(start: &Path) -> Result<Self>

Resolve the repository from start. The scratch roots come from the distribution’s provider declarations, located the way every command locates the share; a checkout with no share in reach declares none, and a temporary checkout is then what its path says it is.

Source

pub fn over(identity: RepositoryIdentity) -> Result<Self>

The service over an identity already resolved.

Source

pub fn over_with( identity: RepositoryIdentity, scratch_roots: Vec<ScratchRoot>, ) -> Result<Self>

The service over an identity, with the scratch roots given rather than located.

Source

pub fn scratch_roots(&self) -> &[ScratchRoot]

The scratch roots in force, expanded.

Source

pub fn identity(&self) -> &RepositoryIdentity

The repository this service speaks for.

Source

pub fn container(&self) -> &ResolvedPath

The canonical container.

Source

pub fn expected_path_of(&self, branch: &str) -> Result<PathBuf>

Where the worktree of branch belongs.

Source

pub fn judge( &self, record: &WorktreeRecord, detail: Detail, branches: &BTreeMap<String, BranchRef>, ) -> WorktreeState

Everything the topology says about one registered work tree. The one place a standing is decided.

Source

pub fn scratch_root_of(&self, path: &ResolvedPath) -> Option<ScratchRoot>

The scratch root a path lies under, when it does. The roots are the declarations’ (share/providers.yaml): the tool’s own temporary directories and every provider’s, such as .claude/worktrees/ under the primary checkout, which Claude Code creates and removes with the session that asked for it, or the thread directory an orchestrator keeps under its data directory. A root the primary checkout itself lives under is skipped, as a test fixture’s temporary directory is: nothing beside the repository is a scratch checkout of it.

Source

pub fn ephemeral_root_of(&self, path: &ResolvedPath) -> Option<PathBuf>

Self::scratch_root_of, the path alone.

Source

pub fn topology(&self, detail: Detail) -> Result<RepositoryTopology>

The whole topology.

Source

pub fn status(&self) -> Result<StatusReport>

Where this call is, and whether that is where it belongs.

Source

pub fn guard(&self) -> Result<GuardVerdict>

The guard: may a mutation proceed from the work tree this call came from?

Source

pub fn inspect(&self, branch: &str) -> Result<InspectReport>

One branch: where its worktree belongs and what is there.

Source

pub fn resolve(&self, selector: &str) -> Result<WorktreeRecord>

Resolve a selector to exactly one registered work tree: an exact branch name, or an exact path. Nothing is matched by prefix, substring or similarity — these selectors are given to commands that delete things.

Source

pub fn create(&self, request: &CreateRequest) -> Result<CreateReport>

Create the canonical worktree of a branch. The destination is derived and never given. Everything that could go wrong is checked before git is asked to do anything, so a refusal leaves the repository exactly as it was.

Source

pub fn ensure(&self, request: &CreateRequest) -> Result<CreateReport>

The same, answering the existing canonical worktree rather than refusing when it is already there.

Source

pub fn remove(&self, selector: &str, force: bool) -> Result<RemoveReport>

Remove one linked worktree. Never a branch, never the primary checkout, never uncommitted work without force.

Source

pub fn repair(&self, dry_run: bool) -> Result<RepairReport>

Drop the registrations of work trees whose directories are gone, and let git repair the administrative links of the ones that exist. Deletes no directory.

Source§

impl WorktreeService

Source

pub fn uncommitted(&self, threshold: &Threshold) -> Result<UncommittedReport>

Every linked work tree holding uncommitted work, with how much, how old, what holds it and whether it is abandoned against threshold. Reads every work tree and writes none: see the module documentation.

use majordomus_cli::worktree::{Threshold, WorkStanding, WorktreeService};
use std::path::Path;
use std::process::Command;
let dir = tempfile::tempdir().unwrap();
let git = |cwd: &Path, args: &[&str]| {
    let ok = Command::new("git")
        .args(["-c", "user.name=t", "-c", "user.email=t@t", "-c", "commit.gpgsign=false"])
        .args(args)
        .current_dir(cwd)
        .status()
        .unwrap();
    assert!(ok.success(), "git {args:?}");
};
let repo = dir.path().join("repo");
std::fs::create_dir_all(&repo).unwrap();
git(&repo, &["init", "-q"]);
git(&repo, &["commit", "-q", "--allow-empty", "-m", "init"]);
let (clean, dirty) = (dir.path().join("clean"), dir.path().join("dirty"));
git(&repo, &["worktree", "add", "-q", "-b", "work/clean", clean.to_str().unwrap()]);
git(&repo, &["worktree", "add", "-q", "-b", "work/dirty", dirty.to_str().unwrap()]);
std::fs::write(dirty.join("new.txt"), "work\n").unwrap();

let threshold = Threshold::resolve(Some("12h"), None).unwrap();
let report = WorktreeService::open(&repo).unwrap().uncommitted(&threshold).unwrap();
assert_eq!(report.tallies.measured, 2, "both linked work trees were read");
assert_eq!(report.worktrees.len(), 1, "only the one with work is listed");
let w = &report.worktrees[0];
assert_eq!((w.label.as_str(), w.paths, w.work.untracked), ("work/dirty", 1, 1));
assert_eq!(w.standing, WorkStanding::Recent, "written a moment ago");

Trait Implementations§

Source§

impl Clone for WorktreeService

Source§

fn clone(&self) -> WorktreeService

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for WorktreeService

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

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
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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.

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more