use std::io;
use std::path::Path;
use std::process::Command;
pub mod aliases;
pub mod attr;
pub mod cat_file;
pub mod config;
pub mod diff_index;
pub mod endpoint;
pub mod extension;
pub mod fetch_prune;
pub mod http_options;
pub mod path;
pub mod pktline;
pub mod refs;
pub mod rev_list;
pub mod scanner;
pub use attr::AttrSet;
pub use config::ConfigScope;
pub use http_options::{HttpOptions, extra_headers_for, lfs_url_bool};
pub use path::{git_common_dir, git_dir, lfs_alternate_dirs, lfs_dir, work_tree_root};
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("io error invoking git: {0}")]
Io(#[from] io::Error),
#[error("git: {0}")]
Failed(String),
}
pub(crate) fn run_git(cwd: &Path, args: &[&str]) -> Result<String, Error> {
let out = Command::new("git").arg("-C").arg(cwd).args(args).output()?;
if !out.status.success() {
return Err(Error::Failed(
String::from_utf8_lossy(&out.stderr).trim().to_owned(),
));
}
Ok(String::from_utf8(out.stdout)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?
.trim()
.to_owned())
}
#[cfg(test)]
pub(crate) mod tests {
pub mod commit_helper {
use std::path::Path;
use std::process::Command;
use tempfile::TempDir;
pub fn init_repo() -> TempDir {
for var in ["GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE"] {
assert!(
std::env::var_os(var).is_none(),
"{var} is set in the test process — git subprocesses \
will ignore the per-test tempdir. Run via \
`just pre-commit` (which strips it) or \
`env -u {var} cargo test`."
);
}
let tmp = TempDir::new().unwrap();
run(tmp.path(), &["init", "--quiet", "--initial-branch=main"]);
run(tmp.path(), &["config", "user.email", "test@example.com"]);
run(tmp.path(), &["config", "user.name", "test"]);
run(tmp.path(), &["config", "commit.gpgsign", "false"]);
tmp
}
pub fn commit_file(repo: &TempDir, path: &str, content: &[u8]) {
std::fs::write(repo.path().join(path), content).unwrap();
run(repo.path(), &["add", path]);
run(
repo.path(),
&["commit", "--quiet", "-m", &format!("add {path}")],
);
}
pub fn head_oid(repo: &TempDir) -> String {
let out = Command::new("git")
.arg("-C")
.arg(repo.path())
.args(["rev-parse", "HEAD"])
.output()
.unwrap();
assert!(out.status.success());
String::from_utf8_lossy(&out.stdout).trim().to_owned()
}
fn run(cwd: &Path, args: &[&str]) {
let status = Command::new("git")
.arg("-C")
.arg(cwd)
.args(args)
.status()
.unwrap();
assert!(status.success(), "git {args:?} failed");
}
}
}