git_next_core/git/
graph.rs1use 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
12fn 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
39pub 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}