Skip to main content

tldr_core/git/
mod.rs

1//! Git operations module
2//!
3//! Provides git-related utilities for churn analysis and other git-based commands.
4
5use std::path::Path;
6use std::process::Command;
7
8use crate::error::TldrError;
9use crate::TldrResult;
10
11/// Check if a path is inside a git repository
12pub fn is_git_repository(path: &Path) -> bool {
13    Command::new("git")
14        .arg("rev-parse")
15        .arg("--git-dir")
16        .current_dir(path)
17        .output()
18        .map(|o| o.status.success())
19        .unwrap_or(false)
20}
21
22/// Check if repository is a shallow clone
23pub fn is_shallow_clone(path: &Path) -> bool {
24    Command::new("git")
25        .arg("rev-parse")
26        .arg("--is-shallow-repository")
27        .current_dir(path)
28        .output()
29        .map(|o| {
30            o.status.success()
31                && String::from_utf8_lossy(&o.stdout).trim() == "true"
32        })
33        .unwrap_or(false)
34}
35
36/// Get git log output with specified format
37pub fn git_log(
38    path: &Path,
39    since_days: u32,
40    format: &str,
41    extra_args: &[&str],
42) -> TldrResult<String> {
43    let since = format!("--since={} days ago", since_days);
44    let format_arg = format!("--pretty=format:{}", format);
45
46    let mut cmd = Command::new("git");
47    cmd.arg("log")
48        .arg(&since)
49        .arg(&format_arg)
50        .current_dir(path);
51
52    for arg in extra_args {
53        cmd.arg(arg);
54    }
55
56    let output = cmd.output().map_err(|e| {
57        TldrError::GitError(format!("Failed to run git log: {}", e))
58    })?;
59
60    if !output.status.success() {
61        let stderr = String::from_utf8_lossy(&output.stderr);
62        return Err(TldrError::GitError(format!(
63            "git log failed: {}",
64            stderr
65        )));
66    }
67
68    Ok(String::from_utf8_lossy(&output.stdout).to_string())
69}
70
71/// Get git log with numstat (lines added/deleted per file)
72pub fn git_log_numstat(path: &Path, since_days: u32) -> TldrResult<String> {
73    let since = format!("--since={} days ago", since_days);
74
75    let output = Command::new("git")
76        .arg("log")
77        .arg(&since)
78        .arg("--numstat")
79        .arg("--format=")
80        .current_dir(path)
81        .output()
82        .map_err(|e| {
83            TldrError::GitError(format!("Failed to run git log: {}", e))
84        })?;
85
86    if !output.status.success() {
87        let stderr = String::from_utf8_lossy(&output.stderr);
88        return Err(TldrError::GitError(format!(
89            "git log --numstat failed: {}",
90            stderr
91        )));
92    }
93
94    Ok(String::from_utf8_lossy(&output.stdout).to_string())
95}