mod analyzer;
use clap::Parser;
use std::{env, fs, process};
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
#[arg(short, long, default_value = "")]
repo_path: String,
#[arg(short, long, default_value = "")]
after: String,
#[arg(short, long, default_value = "")]
before: String,
#[arg(short, long, default_value = "")]
user: String,
}
fn main() {
let args = Args::parse();
let current_dir = if !args.repo_path.is_empty() {
args.repo_path.clone()
} else {
env::current_dir()
.expect("Failed to get current directory")
.to_string_lossy()
.to_string()
};
if !check_directory_and_git(¤t_dir) {
process::exit(1);
}
let user_name = if args.user.is_empty() {
analyzer::get_user_name()
} else {
args.user.clone()
};
let repo = analyzer::get_repo(¤t_dir);
let commits = analyzer::get_commits(&repo, &args.after, &args.before);
let stats = analyzer::get_commit_stats(&repo, &commits.unwrap(), &user_name);
analyzer::show_commit_stats(&stats);
println!();
analyzer::show_coding_habits();
}
fn check_directory_and_git(directory_path: &str) -> bool {
match fs::metadata(directory_path) {
Ok(metadata) => {
if !metadata.is_dir() {
eprintln!("Error: The specified path is not a directory.");
return false;
}
}
Err(_) => {
eprintln!("Error: Directory does not exist.");
return false;
}
}
let git_path = format!("{}/.git", directory_path);
if fs::metadata(git_path).is_err() {
println!("Error: Directory is not a Git repository.");
return false;
}
true
}
#[cfg(test)]
mod tests {
use crate::{check_directory_and_git, main};
#[test]
fn test_check_directory_and_git() {
assert!(
check_directory_and_git("."),
"Failed to check current directory"
);
assert!(
!check_directory_and_git("/invalid/path"),
"Failed to check non-existing directory"
);
assert!(
!check_directory_and_git("/Users"),
"Failed to check non-git directory"
);
}
#[test]
fn run_main_successfully() {
main();
}
}