Skip to main content

Repository

Struct Repository 

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

A lower-level handle for querying changes in a VCS repository worktree.

Most users should start with crate::AllowOptions, which implements the crate’s built-in --allow-* safe-to-modify policy.

Use this type when you need to discover a repository and inspect whether files are dirty and/or staged directly in order to implement custom policy logic. Dirty files include modified tracked files and untracked files.

Repositories without a worktree, such as Git bare repositories, are not represented by this type.

§Example

The following example shows how to implement a custom safe-to-modify policy by querying repository changes directly.

use std::{error::Error, path::Path};

use vcs_modify_guard::repository::Repository;

struct PolicyOptions {
    allow_no_vcs: bool,
    allow_dirty: bool,
    allow_staged: bool,
}

fn ensure_safe_to_modify(target: &Path, options: &PolicyOptions) -> Result<(), Box<dyn Error>> {
    // Match `cargo fix` exactly:
    // - `--allow-no-vcs` allows running even when no repository is found.
    // - `--allow-dirty` allows worktree changes, staged changes, and
    //   untracked files.
    // - `--allow-staged` allows staged changes, but still rejects
    //   worktree changes and untracked files.
    if options.allow_no_vcs {
        return Ok(());
    }

    let Some(repo) = Repository::discover(target)? else {
        return Err("no VCS found for the target path".into());
    };

    let Some(changes) = repo.repository_changes()? else {
        return Ok(());
    };

    if options.allow_dirty {
        return Ok(());
    }

    if changes.has_dirty_files() {
        return Err("the repository containing the target path has uncommitted changes".into());
    }

    if options.allow_staged {
        return Ok(());
    }

    if changes.has_staged_files() {
        return Err("the repository containing the target path has staged changes".into());
    }

    Ok(())
}

See the repository example for a complete command-line application.

Implementations§

Source§

impl Repository

Source

pub fn discover<P>(path: P) -> Result<Option<Self>, ModifyGuardError>
where P: AsRef<Path>,

Discovers the repository containing path.

This searches path and its parent directories for a repository supported by one of the enabled backends.

Returns Ok(Some(_)) if a supported repository worktree is found, or Ok(None) if no supported repository is found.

§Errors

Returns an error if:

  • a backend fails while probing path
  • the discovered repository does not provide a worktree for file change checks
Source

pub fn open<P>(path: P) -> Result<Self, ModifyGuardError>
where P: AsRef<Path>,

Opens the repository at path.

Unlike Self::discover, this does not search parent directories. path must identify a repository directly according to the enabled backend.

§Errors

Returns an error if:

  • path does not refer to a supported repository worktree
  • the backend fails to open it
Source

pub fn worktree(&self) -> &Path

Returns the root directory of the repository worktree.

Source

pub fn resolve_path<P>(&self, path: P) -> Result<PathBuf, ModifyGuardError>
where P: AsRef<Path>,

Resolves a path to a repository worktree-relative path.

This follows symlinks and canonicalizes the existing prefix of path. The returned path is relative to Self::worktree.

If path does not exist in the worktree, this method may still succeed when the missing path is lexically within the worktree, such as a path to a deleted tracked file.

Use this when you start with an absolute path or a path relative to the current working directory and need the corresponding worktree-relative path for Self::path_changes or Self::file_change.

§Errors

Returns an error if:

  • path does not resolve to a path within Self::worktree
  • path could not be resolved to a canonical path for any other reason
Source

pub fn repository_changes( &self, ) -> Result<Option<RepositoryChanges>, ModifyGuardError>

Returns the aggregate file changes in the repository worktree.

Returns Ok(None) if the repository has no dirty or staged files. Clean tracked files are not included in this aggregate change set. Files ignored by the VCS are also omitted because this crate is intended for --allow-* style checks, which treat them the same as clean files.

Paths in the returned changes are relative to Self::worktree.

§Errors

Returns an error if the backend fails to query repository changes.

Source

pub fn path_changes<P>( &self, wt_path: P, ) -> Result<Option<RepositoryChanges>, ModifyGuardError>
where P: AsRef<Path>,

Returns the aggregate file changes for the worktree-relative wt_path within the repository.

If wt_path resolves to a file path, the returned change set contains at most that file. If wt_path resolves to a directory path, the returned change set contains changes for files under that directory. The repository worktree root is also accepted.

Returns Ok(None) if the resolved path has no dirty or staged files. Clean tracked files are not included in this aggregate change set. Files ignored by the VCS are also omitted because this crate is intended for --allow-* style checks, which treat them the same as clean files.

Paths in the returned changes are relative to Self::worktree.

wt_path is interpreted relative to Self::worktree. If you have an absolute path or a path relative to the current working directory, use Self::resolve_path first. Symlinks are followed.

If the resolved path does not exist in the worktree, this method may still return changes when the path refers to paths known to the VCS, such as a deleted tracked file path.

§Errors

Returns an error if:

  • wt_path does not resolve to a path within Self::worktree
  • wt_path does not exist in the worktree and does not refer to a path known to the VCS
  • wt_path could not be resolved to a canonical path for any other reason
  • the backend fails to query changes for wt_path for any other reason
Source

pub fn file_change<P>( &self, wt_path: P, ) -> Result<Option<FileChange>, ModifyGuardError>
where P: AsRef<Path>,

Returns the dirty and/or staged change for the worktree-relative file path wt_path within the repository, if any.

Returns Ok(None) if the resolved file path is clean or ignored by the VCS.

If this method returns Ok(Some(change)), the returned FileChange describes the resolved file path.

wt_path is interpreted relative to Self::worktree. If you have an absolute path or a path relative to the current working directory, use Self::resolve_path first. Symlinks are followed.

If the resolved path exists in the worktree, it must be a file. If it does not exist in the worktree, this method may still return a change when the path refers to a tracked file path known to the VCS, such as a deletion change. FileChange::wt_path may differ from the path passed to this method when the input reaches the same file path through symlinks or other equivalent non-canonical forms.

A file may be both staged and dirty at the same time if it has staged changes and additional unstaged tracked changes.

This operation is intended for file paths. It does not perform rename detection.

§Errors

Returns an error if:

  • wt_path does not resolve to a path within Self::worktree
  • the resolved path exists in the worktree but does not resolve to a file
  • wt_path does not exist in the worktree and does not refer to a tracked path known to the VCS
  • wt_path could not be resolved to a canonical path for any other reason
  • the backend fails to query file changes for any other reason

Trait Implementations§

Source§

impl Debug for Repository

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
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> Same for T

Source§

type Output = T

Should always be Self
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.