1use std::path::{Path, PathBuf};
4use std::process::{Command, Output};
5
6pub use fallow_types::churn::ChurnTrend;
7use rustc_hash::FxHashMap;
8
9use crate::core_backend;
10
11pub type ChurnSpawnHook = fn(&mut Command) -> std::io::Result<Output>;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct SinceDuration {
17 pub git_after: String,
19 pub display: String,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq)]
25pub struct AuthorContribution {
26 pub commits: u32,
28 pub weighted_commits: f64,
30 pub first_commit_ts: u64,
32 pub last_commit_ts: u64,
34}
35
36#[derive(Debug, Clone)]
38pub struct FileChurn {
39 pub path: PathBuf,
41 pub commits: u32,
43 pub weighted_commits: f64,
45 pub lines_added: u32,
47 pub lines_deleted: u32,
49 pub trend: ChurnTrend,
51 pub authors: FxHashMap<u32, AuthorContribution>,
53}
54
55#[derive(Debug, Clone)]
57pub struct ChurnResult {
58 pub files: FxHashMap<PathBuf, FileChurn>,
60 pub shallow_clone: bool,
62 pub author_pool: Vec<String>,
64}
65
66pub fn set_spawn_hook(hook: ChurnSpawnHook) {
68 core_backend::set_churn_spawn_hook(hook);
69}
70
71pub fn parse_since(input: &str) -> Result<SinceDuration, String> {
77 core_backend::parse_since(input)
78}
79
80#[must_use]
82pub fn analyze_churn(root: &Path, since: &SinceDuration) -> Option<ChurnResult> {
83 core_backend::analyze_churn(root, since)
84}
85
86pub fn analyze_churn_from_file(path: &Path, root: &Path) -> Result<ChurnResult, String> {
92 core_backend::analyze_churn_from_file(path, root)
93}
94
95#[must_use]
97pub fn is_git_repo(root: &Path) -> bool {
98 core_backend::is_git_repo(root)
99}
100
101#[must_use]
103pub fn analyze_churn_cached(
104 root: &Path,
105 since: &SinceDuration,
106 cache_dir: &Path,
107 no_cache: bool,
108) -> Option<(ChurnResult, bool)> {
109 core_backend::analyze_churn_cached(root, since, cache_dir, no_cache)
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn parse_since_returns_engine_owned_duration() {
118 let duration = parse_since("6m").expect("duration should parse");
119 assert_eq!(duration.git_after, "6 months ago");
120 assert_eq!(duration.display, "6 months");
121 }
122}