summaryrefslogtreecommitdiffstats
path: root/src/sorter.rs
blob: 049b8d27e6e7d80075f6e39d721907ab42f47aa5 (plain)
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
use std::{cmp::Ordering, path::PathBuf};

use git2::{BranchType, Repository};
use tracing::error;

pub trait Sorter {
    #[allow(clippy::ptr_arg)]
    fn compare(a: &PathBuf, b: &PathBuf) -> Ordering;

    fn sort(vec: &mut Vec<PathBuf>) {
        vec.sort_unstable_by(Self::compare);
    }
}

pub struct GitSorter;

impl GitSorter {
    fn get_commit(path: &PathBuf) -> Result<i64, git2::Error> {
        let repo = Repository::open(path)?;
        let mut branches = repo.branches(Some(BranchType::Local))?;
        branches.try_fold(0, |latest, branch| {
            let branch = branch?.0;

            let name = branch
                .name()?
                .ok_or_else(|| git2::Error::from_str("Failed to find branch"))?;

            repo.revparse_single(name)?
                .peel_to_commit()
                .map(|c| c.time().seconds().max(latest))
        })
    }
}

impl Sorter for GitSorter {
    fn compare(path_a: &PathBuf, path_b: &PathBuf) -> Ordering {
        let commit_a = Self::get_commit(path_a);
        let commit_b = Self::get_commit(path_b);

        match (commit_a, commit_b) {
            (Ok(a), Ok(b)) => a.cmp(&b),
            (Ok(_), Err(error_b)) => {
                error!(?path_b, ?error_b, "Error while comparing git repos");
                Ordering::Less
            }
            (Err(error_a), Ok(_)) => {
                error!(?path_a, ?error_a, "Error while comparing git repos");
                Ordering::Greater
            }
            (Err(error_a), Err(error_b)) => {
                error!(
                    ?path_a,
                    ?error_a,
                    ?path_b,
                    ?error_b,
                    "Error while comparing git repos"
                );
                Ordering::Equal
            }
        }
    }
}