diary/utils/
git.rs

1use std::path::Path;
2
3use git2::{Commit, Direction, ObjectType, Repository};
4
5pub fn find_last_commit(repo: &Repository) -> Result<Option<Commit>, git2::Error> {
6    let head = repo.head();
7
8    let obj = match head {
9        Ok(head_ref) => head_ref.resolve()?.peel(ObjectType::Commit)?,
10        Err(_) => return Ok(None),
11    };
12
13    Ok(Some(obj.into_commit().map_err(|_| {
14        git2::Error::from_str("Couldn't find commit") // uncovered.
15    })?))
16}
17
18pub fn add_and_commit(
19    repo: &Repository,
20    file_path: &Path,
21    message: &str,
22) -> Result<(), git2::Error> {
23    let mut index = repo.index()?;
24    index.add_path(file_path)?;
25    index.write()?;
26    let oid = index.write_tree()?;
27    let signature = Repository::signature(repo)?;
28    let tree = repo.find_tree(oid)?;
29
30    let last_commit = find_last_commit(repo)?;
31
32    if let Some(reference) = last_commit {
33        repo.commit(
34            Some("HEAD"),
35            &signature,
36            &signature,
37            message,
38            &tree,
39            &[&reference],
40        )?;
41    } else {
42        repo.commit(Some("HEAD"), &signature, &signature, message, &tree, &[])?;
43    }
44    Ok(())
45}
46
47pub fn push_to_origin(repo: &Repository) -> Result<(), git2::Error> {
48    let mut remote = repo.find_remote("origin")?;
49    remote.connect(Direction::Push)?; // uncovered.
50    remote.push(&["refs/heads/master:refs/heads/master"], None) // uncovered.
51}
52
53#[cfg(test)]
54mod test {
55    use git2::Repository;
56
57    use super::find_last_commit;
58    use crate::ops::testing;
59
60    #[test]
61    fn no_commit() {
62        let dir = testing::temp_path();
63
64        let repo = Repository::init(dir).unwrap();
65
66        let last_commit = find_last_commit(&repo).unwrap();
67
68        assert!(last_commit.is_none())
69    }
70}