-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgit.rs
70 lines (59 loc) · 2.13 KB
/
git.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use std::{fs, io::Write, path::Path};
use anyhow::Result;
use assert_fs::fixture::PathChild;
use git2::{Commit, Index, IndexAddOption, Repository, Signature};
/// Initializes a Git repository at the given location.
///
/// `gitignore`: How the `.gitignore` file should look like. May contain
/// newlines to set multiple rules.
///
/// `commit`: Whether to do `git add .` and `git commit` afterwards.
pub fn git_init<T>(parent: &T, gitignore: &str, commit: bool)
where
T: PathChild + AsRef<Path>,
{
fs::create_dir_all(parent.as_ref()).unwrap();
let repo = Repository::init(parent).unwrap();
if !gitignore.is_empty() {
let gitignore_path = parent.child(".gitignore");
let mut gitignore_file = fs::OpenOptions::new()
.create(true)
.append(true)
.open(gitignore_path)
.unwrap();
gitignore_file.write_all(gitignore.as_bytes()).unwrap();
}
if commit {
let mut index = git_add(&repo, &["."]).unwrap();
git_commit(&repo, &mut index, "test").unwrap();
}
}
// see https://libgit2.org/libgit2/ex/HEAD/add.html
fn git_add(repo: &Repository, pathspecs: &[&str]) -> Result<Index> {
let mut index = repo.index()?;
index.add_all(pathspecs, IndexAddOption::DEFAULT, None)?;
index.write()?;
Ok(index)
}
// see https://libgit2.org/libgit2/ex/HEAD/commit.html
fn git_commit(repo: &Repository, index: &mut Index, message: &str) -> Result<()> {
let tree_oid = index.write_tree()?;
let tree = repo.find_tree(tree_oid)?;
let signature = Signature::now("makeclean-test", "makeclean-test@example.com")?;
let author = &signature;
let committer = &signature;
let parents = match repo.head() {
Ok(head) => vec![head.peel_to_commit()?],
Err(e) => {
if e.code() == git2::ErrorCode::UnbornBranch {
// No commits yet - HEAD does not exist
vec![]
} else {
return Err(e.into());
}
}
};
let parents: Vec<&Commit> = parents.iter().collect();
repo.commit(Some("HEAD"), author, committer, message, &tree, &parents)?;
Ok(())
}