Skip to main content

binocular/search/sources/git/
preview.rs

1use super::scope::if_empty_then;
2use anyhow::{bail, Context};
3use std::path::Path;
4use std::process::Command;
5
6pub fn read_history_blob(
7    repo_root: &Path,
8    commit: &str,
9    file_path: &Path,
10) -> anyhow::Result<Vec<u8>> {
11    let object = format!("{}:{}", commit, file_path.to_string_lossy());
12    let output = Command::new("git")
13        .arg("show")
14        .arg(&object)
15        .current_dir(repo_root)
16        .output()
17        .with_context(|| format!("failed to read historical blob for {object}"))?;
18
19    if !output.status.success() {
20        let stderr = String::from_utf8_lossy(&output.stderr);
21        bail!(
22            "git show failed for {object}: {}",
23            if_empty_then(stderr.trim(), "unknown git error")
24        );
25    }
26
27    Ok(output.stdout)
28}
29
30pub fn read_branch_preview(repo_root: &Path, branch: &str) -> anyhow::Result<String> {
31    run_git_text(
32        repo_root,
33        &[
34            "log",
35            "--color=always",
36            "--decorate",
37            "--stat",
38            "--max-count=25",
39            branch,
40        ],
41        &format!("failed to read branch preview for {branch}"),
42    )
43}
44
45pub fn read_commit_preview(repo_root: &Path, commit: &str) -> anyhow::Result<String> {
46    run_git_text(
47        repo_root,
48        &[
49            "show",
50            "--color=always",
51            "--stat",
52            "--patch",
53            "--decorate",
54            commit,
55        ],
56        &format!("failed to read commit preview for {commit}"),
57    )
58}
59
60fn run_git_text(repo_root: &Path, args: &[&str], context: &str) -> anyhow::Result<String> {
61    let output = Command::new("git")
62        .args(args)
63        .current_dir(repo_root)
64        .output()
65        .context(context.to_string())?;
66
67    if !output.status.success() {
68        let stderr = String::from_utf8_lossy(&output.stderr);
69        bail!(
70            "{}: {}",
71            context,
72            if_empty_then(stderr.trim(), "unknown git error")
73        );
74    }
75
76    let mut text = String::from_utf8_lossy(&output.stdout).into_owned();
77    if text.trim().is_empty() {
78        text = "No output".to_string();
79    }
80    Ok(text)
81}