vcs-modify-guard 0.1.0

A library for checking whether it is safe to modify files in a VCS worktree.
Documentation

vcs-modify-guard

Maintenance: actively-developed License: MIT OR Apache-2.0 crates.io docs.rs Rust: ^1.96.0 GitHub Actions: CI Codecov

Help CLI tools decide whether it is safe to modify files in a VCS working tree.

vcs-modify-guard helps CLI tools enforce --allow-dirty, --allow-staged, and --allow-no-vcs style checks before they modify files.

Currently, this crate supports Git repositories. Backend selection is controlled by Cargo features; see Feature flags.

API overview

This crate provides two layers of API:

  • AllowOptions is the main entry point. It implements cargo fix-style safe-to-modify checks and returns a ModificationSafety describing whether modification is safe. By default, checks are scoped to the queried path.
  • repository::Repository is a lower-level API for tools that need to discover a repository and inspect whether files are dirty and/or staged to implement their own policy. Dirty files include modified tracked files and untracked files.

Most users should start with AllowOptions. Reach for repository::Repository only when you need custom behavior beyond the built-in --allow-* semantics.

Feature flags

This crate currently supports Git repositories via selectable Git backends.

Backend selection features

  • git-default (enabled by default) enables the default Git backend. Currently, this enables git-gix.
  • git-gix enables the gix backend.
  • git-libgit2 enables the libgit2 backend.
  • git-cli enables the Git CLI backend.

To opt out of the default backend, disable default features and enable the desired backend feature(s) explicitly:

[dependencies]
vcs-modify-guard = {
  version = "0.1.0",
  default-features = false,
  features = ["git-libgit2"]
}

If multiple backends are enabled, they are tried in this fixed priority order: gix, then libgit2, then the Git CLI.

If no backend selection features are enabled, repository discovery reports that no supported repository was found.

Backend configuration features

  • vendored-libgit2 forwards to git2’s vendored-libgit2 feature when git-libgit2 is enabled.

Example

The following example shows how to validate whether a target path is safe to modify before performing an operation that may modify files.

use std::path::{Path, PathBuf};

use clap::Parser;
use vcs_modify_guard::{AllowOptions, ModificationSafety, UnsafeModificationReason};

#[derive(Debug, Parser)]
struct Args {
    /// Process code even if a VCS was not detected.
    #[arg(long)]
    allow_no_vcs: bool,
    /// Process code even if the target path has modified, staged, or
    /// untracked files under it.
    #[arg(long)]
    allow_dirty: bool,
    /// Process code even if the target path has staged changes under it.
    #[arg(long)]
    allow_staged: bool,
    /// Target path to process. Defaults to the current working directory.
    target: Option<PathBuf>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args = Args::parse();

    let target = args.target.as_deref().unwrap_or_else(|| Path::new("."));
    let safety = AllowOptions::new()
        .allow_no_vcs(args.allow_no_vcs)
        .allow_dirty(args.allow_dirty)
        .allow_staged(args.allow_staged)
        .check_safe_to_modify(target)?;

    match safety {
        ModificationSafety::Safe => {}
        ModificationSafety::Unsafe(reason) => match reason {
            UnsafeModificationReason::NoVcs => {
                return Err("blocked by no VCS".into());
            }
            UnsafeModificationReason::Dirty { .. } => {
                return Err("blocked by dirty files".into());
            }
            UnsafeModificationReason::Staged { .. } => {
                return Err("blocked by staged changes".into());
            }
            _ => {
                return Err("blocked by unsafe modifications".into());
            }
        },
    }

    eprintln!("Proceeding...");

    Ok(())
}

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

If you need custom policy logic instead of the built-in --allow-* behavior, see the repository module for direct repository discovery and change query APIs.

Minimum supported Rust version (MSRV)

The minimum supported Rust version is Rust 1.96.0.

While a crate is a pre-release status (0.x.x) it may have its MSRV bumped in a patch release. Once a crate has reached 1.x, any MSRV bump will be accompanied by a new minor version.

License

This project is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

See CONTRIBUTING.md.