git_next_core/git/
graph.rs

1//
2use std::borrow::ToOwned;
3
4use take_until::TakeUntilExt;
5
6use crate::{newtype, GitDir, RepoBranches};
7
8use super::RepoDetails;
9
10newtype!(Log, Vec<String>, Default, Hash, "Git log of branches");
11
12// create a graph to log relative positions
13//
14// ANCESTOR=$(git merge-base --octopus origin/main origin/next origin/dev)
15// SHORT_ANCESTOR=$(echo $ANCESTOR | cut -b -7)
16fn ancesstor(gitdir: &GitDir, branches: &RepoBranches) -> Option<String> {
17    let result = std::process::Command::new("/usr/bin/git")
18        .current_dir(gitdir.to_path_buf())
19        .args([
20            "merge-base",
21            "--octopus",
22            format!("origin/{}", branches.main()).as_str(),
23            format!("origin/{}", branches.next()).as_str(),
24            format!("origin/{}", branches.dev()).as_str(),
25        ])
26        .output();
27    if let Ok(output) = result {
28        return String::from_utf8_lossy(output.stdout.as_slice())
29            .split('\n')
30            .take(1)
31            .map(|line| line.chars().take(7).collect::<String>())
32            .collect::<Vec<_>>()
33            .first()
34            .cloned();
35    }
36    None
37}
38
39// git log --oneline --graph --decorate origin/main origin/dev origin/next | awk "1;/$SHORT_ANCESTOR/{exit}"
40pub fn log(repo_details: &RepoDetails) -> Log {
41    if let Some(repo_config) = &repo_details.repo_config {
42        let branches = repo_config.branches();
43        let result = std::process::Command::new("/usr/bin/git")
44            .current_dir(repo_details.gitdir().to_path_buf())
45            .args([
46                "log",
47                "--oneline",
48                "--graph",
49                "--decorate",
50                format!("origin/{}", branches.main()).as_str(),
51                format!("origin/{}", branches.next()).as_str(),
52                format!("origin/{}", branches.dev()).as_str(),
53            ])
54            .output();
55        if let Ok(output) = result {
56            if let Some(ancestor) = ancesstor(repo_details.gitdir(), branches) {
57                return String::from_utf8_lossy(output.stdout.as_slice())
58                    .split('\n')
59                    .take_until(|line| line.contains(&ancestor))
60                    .map(str::trim)
61                    .map(ToOwned::to_owned)
62                    .collect::<Vec<_>>()
63                    .into();
64            }
65        }
66    }
67    Log::default()
68}