use std::{
error::Error,
path::{Path, PathBuf},
};
use clap::Parser;
use vcs_modify_guard::repository::Repository;
#[derive(Debug, Parser)]
struct Args {
#[arg(long)]
allow_no_vcs: bool,
#[arg(long)]
allow_dirty: bool,
#[arg(long)]
allow_staged: bool,
target: Option<PathBuf>,
}
fn main() -> Result<(), Box<dyn Error>> {
let args = Args::parse();
let target = args.target.as_deref().unwrap_or_else(|| Path::new("."));
let options = Options {
allow_no_vcs: args.allow_no_vcs,
allow_staged: args.allow_staged,
allow_dirty: args.allow_dirty,
};
ensure_safe_to_modify(target, &options)?;
eprintln!("Proceeding...");
Ok(())
}
struct Options {
allow_no_vcs: bool,
allow_dirty: bool,
allow_staged: bool,
}
fn ensure_safe_to_modify(target: &Path, options: &Options) -> Result<(), Box<dyn Error>> {
if options.allow_no_vcs {
eprintln!("--allow-no-vcs is set, skipping repository checks.");
return Ok(());
}
let Some(repo) = Repository::discover(target)? else {
return Err("no VCS found for the target path; if you'd like to suppress this error pass `--allow-no-vcs`".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; if you'd like to suppress this error pass `--allow-dirty`".into(),
);
}
if options.allow_staged {
return Ok(());
}
if changes.has_staged_files() {
return Err(
"the repository containing the target path has staged changes; if you'd like to suppress this error pass `--allow-staged`".into(),
);
}
Ok(())
}