git_x/
info.rs

1use std::path::Path;
2use std::process::Command;
3
4pub fn run() {
5    // Get repo name
6    let output = Command::new("git")
7        .args(["rev-parse", "--show-toplevel"])
8        .output()
9        .expect("Failed to get repo root");
10    let repo_path = String::from_utf8_lossy(&output.stdout).trim().to_string();
11    let repo_name = extract_repo_name(&repo_path);
12
13    // Get current branch
14    let output = Command::new("git")
15        .args(["rev-parse", "--abbrev-ref", "HEAD"])
16        .output()
17        .expect("Failed to get current branch");
18    let branch = String::from_utf8_lossy(&output.stdout).trim().to_string();
19
20    // Get upstream tracking branch
21    let output = Command::new("git")
22        .args(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"])
23        .output()
24        .unwrap_or_else(|_| panic!("Failed to get upstream for {branch}"));
25    let tracking_raw = String::from_utf8_lossy(&output.stdout).trim().to_string();
26    let tracking = format_tracking_branch(&tracking_raw);
27
28    // Get ahead/behind counts
29    let output = Command::new("git")
30        .args(["rev-list", "--left-right", "--count", "HEAD...@{u}"])
31        .output()
32        .expect("Failed to get ahead/behind count");
33    let counts = String::from_utf8_lossy(&output.stdout).trim().to_string();
34    let (ahead, behind) = parse_ahead_behind_counts(&counts);
35
36    // Get last commit message and relative date
37    let output = Command::new("git")
38        .args(["log", "-1", "--pretty=format:%s (%cr)"])
39        .output()
40        .expect("Failed to get last commit");
41    let last_commit = String::from_utf8_lossy(&output.stdout).trim().to_string();
42
43    let bold = console::Style::new().bold();
44
45    // Print all the info
46    println!("Repo: {}", bold.apply_to(repo_name));
47    println!("Branch: {}", bold.apply_to(branch));
48    println!("Tracking: {}", bold.apply_to(tracking));
49    println!(
50        "Ahead: {} Behind: {}",
51        bold.apply_to(&ahead),
52        bold.apply_to(&behind)
53    );
54    println!("Last Commit: \"{}\"", bold.apply_to(last_commit));
55}
56
57// Helper function to extract repo name from path
58pub fn extract_repo_name(repo_path: &str) -> String {
59    Path::new(repo_path)
60        .file_name()
61        .map(|s| s.to_string_lossy().into_owned())
62        .unwrap_or_default()
63}
64
65// Helper function to parse ahead/behind counts
66pub fn parse_ahead_behind_counts(counts_output: &str) -> (String, String) {
67    let mut parts = counts_output.split_whitespace();
68    let ahead = parts.next().unwrap_or("0").to_string();
69    let behind = parts.next().unwrap_or("0").to_string();
70    (ahead, behind)
71}
72
73// Helper function to format tracking branch
74pub fn format_tracking_branch(tracking_raw: &str) -> String {
75    if tracking_raw.is_empty() {
76        "(no upstream)".to_string()
77    } else {
78        tracking_raw.to_string()
79    }
80}