use git2::{Oid, Repository, RepositoryInitOptions};
use std::fs::File;
use std::path::Path;
use tempfile::TempDir;
macro_rules! t {
($e:expr) => {
match $e {
Ok(e) => e,
Err(e) => panic!("{} failed with {}", stringify!($e), e),
}
};
}
pub fn repo_init() -> (TempDir, Repository) {
let td = TempDir::new().unwrap();
let mut opts = RepositoryInitOptions::new();
opts.initial_head("master");
let repo = Repository::init_opts(td.path(), &opts).unwrap();
{
let mut config = repo.config().unwrap();
config.set_str("user.name", "name").unwrap();
config.set_str("user.email", "email").unwrap();
let mut index = repo.index().unwrap();
let id = index.write_tree().unwrap();
let tree = repo.find_tree(id).unwrap();
let sig = repo.signature().unwrap();
repo.commit(Some("HEAD"), &sig, &sig, "initial\n\nbody", &tree, &[])
.unwrap();
}
(td, repo)
}
pub fn commit(repo: &Repository, filename: &str, msg: Option<&str>) -> (Oid, Oid) {
let mut index = t!(repo.index());
let root = repo.path().parent().unwrap();
t!(File::create(root.join(filename)));
t!(index.add_path(Path::new(filename)));
let tree_id = t!(index.write_tree());
let tree = t!(repo.find_tree(tree_id));
let sig = t!(repo.signature());
let head_id = t!(repo.refname_to_id("HEAD"));
let parent = t!(repo.find_commit(head_id));
let msg = if let Some(msg) = msg {
msg
} else {
"some commit"
};
let commit = t!(repo.commit(Some("HEAD"), &sig, &sig, msg, &tree, &[&parent]));
(commit, tree_id)
}
pub fn commit_tag(repo: &Repository, filename: &str, tag: &str) -> (Oid, Oid) {
let (commit, _) = commit(repo, filename, None);
let obj = repo.find_object(commit, None).unwrap();
let sig = repo.signature().unwrap();
let tag = repo.tag(tag, &obj, &sig, "msg", false).unwrap();
(commit, tag)
}
pub fn commit_lightweight_tag(repo: &Repository, filename: &str, tag: &str) -> (Oid, Oid) {
let (commit, _) = commit(repo, filename, None);
let obj = repo.find_object(commit, None).unwrap();
let tag = repo.tag_lightweight(tag, &obj, false).unwrap();
(commit, tag)
}
pub fn new_commit<'a>(
filename: &'a str,
body: &'a str,
) -> Result<(git2::Repository, git2::Oid), Box<dyn std::error::Error>> {
let (dir, _) = repo_init();
let repo = git2::Repository::open(&dir)?;
let (oid, _) = commit(&repo, filename, Some(body));
Ok((repo, oid))
}