index : smol-guess.git

ascending towards madness

use std::{
    collections::HashMap,
    fs::File,
    io::{self, Write},
    path::PathBuf,
    vec,
};

use clap::Parser;
use itertools::Itertools;
use log::{debug, error, info};
use smolguess::{
    core::{LanguageDefinitions, LanguageMatch},
    repository,
};

#[derive(Parser)]
#[command(author, version, about)]
struct CliArgs {
    /// The path to a git repository on disk (required).
    pub repository: String,

    /// Write match data to file (optional).
    #[clap(short, long, name = "FILENAME")]
    pub export: Option<String>,

    /// Display all messages.
    #[clap(short, long)]
    pub verbose: bool,
}

fn main() -> io::Result<()> {
    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init();

    let args: CliArgs = CliArgs::parse();

    let mut stopwatch = stopwatch::Stopwatch::new();
    stopwatch.start();

    let repo_languages: Vec<LanguageMatch> = LanguageDefinitions::default()
        .load_builtins()
        .identify_files(repository::get_bare_repository_files(PathBuf::from(
            args.repository,
        )));

    let grouped_matches: HashMap<_, _> = repo_languages
        .clone()
        .into_iter()
        .group_by(|matched| matched.language.name.clone())
        .into_iter()
        .map(|(group, items)| (group, items.collect_vec()))
        .collect();

    let mut sorted_groups: Vec<_> = grouped_matches.into_iter().collect();
    sorted_groups.sort_by(|(_, first), (_, second)| second.len().cmp(&first.len()));

    stopwatch.stop();

    let json: String = serde_json::to_string_pretty(&sorted_groups)?;

    // Print out the results
    if args.verbose {
        debug!("======== JSON DATA ========");
        println!("{}", json);
        debug!("======== END  DATA ========");
        debug!("Files found: {}", repo_languages.len());
    }

    // Write match data to file
    if args.export.is_some() {
        let file = PathBuf::from(args.export.as_ref().unwrap());

        if !file.is_dir() {
            File::create(file)?.write_all(json.as_bytes())?;
        } else {
            error!(
                "The provided path is a directory: '{}'",
                args.export.unwrap()
            );
        }
    }

    // Output the identified language
    if !sorted_groups.is_empty() {
        let default: (String, Vec<LanguageMatch>) = (String::from("Unknown"), vec![]);

        println!(
            "{}",
            sorted_groups.first().unwrap_or_else(|| { &default }).0
        );
    }

    // Print out the execution time
    if args.verbose {
        info!("Operation completed in: {}", stopwatch)
    }

    Ok(())
}