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
//

use std::borrow::ToOwned;

use take_until::TakeUntilExt;

use crate::{newtype, GitDir, RepoBranches};

use super::RepoDetails;

newtype!(Log, Vec<String>, Default, Hash, "Git log of branches");

// create a graph to log relative positions
//
// ANCESTOR=$(git merge-base --octopus origin/main origin/next origin/dev)
// SHORT_ANCESTOR=$(echo $ANCESTOR | cut -b -7)
fn ancesstor(gitdir: &GitDir, branches: &RepoBranches) -> Option<String> {
    let result = std::process::Command::new("/usr/bin/git")
        .current_dir(gitdir.to_path_buf())
        .args([
            "merge-base",
            "--octopus",
            format!("origin/{}", branches.main()).as_str(),
            format!("origin/{}", branches.next()).as_str(),
            format!("origin/{}", branches.dev()).as_str(),
        ])
        .output();
    if let Ok(output) = result {
        return String::from_utf8_lossy(output.stdout.as_slice())
            .split('\n')
            .take(1)
            .map(|line| line.chars().take(7).collect::<String>())
            .collect::<Vec<_>>()
            .first()
            .cloned();
    }
    None
}

// git log --oneline --graph --decorate origin/main origin/dev origin/next | awk "1;/$SHORT_ANCESTOR/{exit}"
pub fn log(repo_details: &RepoDetails) -> Log {
    if let Some(repo_config) = &repo_details.repo_config {
        let branches = repo_config.branches();
        let result = std::process::Command::new("/usr/bin/git")
            .current_dir(repo_details.gitdir().to_path_buf())
            .args([
                "log",
                "--oneline",
                "--graph",
                "--decorate",
                format!("origin/{}", branches.main()).as_str(),
                format!("origin/{}", branches.next()).as_str(),
                format!("origin/{}", branches.dev()).as_str(),
            ])
            .output();
        if let Ok(output) = result {
            if let Some(ancestor) = ancesstor(repo_details.gitdir(), branches) {
                return String::from_utf8_lossy(output.stdout.as_slice())
                    .split('\n')
                    .take_until(|line| line.contains(&ancestor))
                    .map(str::trim)
                    .map(ToOwned::to_owned)
                    .collect::<Vec<_>>()
                    .into();
            }
        }
    }
    Log::default()
}