mod catch;
mod clean;
mod config;
mod git;
mod history;
mod init;
mod install;
mod migrate;
mod package;
mod package_manager;
mod package_manager_impl;
mod repo;
use crate::config::Config;
use anyhow::{anyhow, Context, Result};
use bugreport::{
bugreport,
collector::{CommandOutput, CompileTimeInformation, EnvironmentVariables, SoftwareVersion},
format::Markdown,
};
use camino::Utf8PathBuf;
use clap::{Arg, ArgAction, ColorChoice, Command};
use log::error;
use simplelog::{ColorChoice as LogColorChoice, LevelFilter, TermLogger, TerminalMode};
use std::path::PathBuf;
fn public_clap_app() -> Command {
clap::command!()
.arg_required_else_help(true)
.color(ColorChoice::Auto)
.subcommand(
Command::new("install")
.about("Install the packages that have been mirrored from other machines")
.arg(
Arg::new("yes")
.short('y')
.long("yes")
.help("Don't prompt the user and try to install everything")
.action(ArgAction::SetTrue),
),
)
.subcommand(Command::new("clean").about("Remove package synching"))
.arg(
Arg::new("config-path")
.short('c')
.help("The location of the configuration file")
.required(false)
.global(true)
.action(ArgAction::Set)
.value_parser(clap::value_parser!(Utf8PathBuf))
.env("EMPLACE_CONFIG"),
)
}
fn safe_main() -> Result<()> {
TermLogger::init(
LevelFilter::Info,
simplelog::Config::default(),
TerminalMode::Mixed,
LogColorChoice::Auto,
)
.context("no interactive terminal")?;
let matches = public_clap_app()
.subcommand(
Command::new("init")
.about("Prints the shell function used to execute emplace")
.arg(
Arg::new("shell")
.value_name("SHELL")
.help(
"The name of the currently running shell\nCurrently supported options: bash, nu, fish & zsh",
)
.required(true)
.action(ArgAction::Set)
)
)
.subcommand(
Command::new("catch")
.about("Capture a command entered in a terminal")
.arg(
Arg::new("line")
.value_name("LINE")
.help("The command as entired in the terminal")
.required(true)
.action(ArgAction::Set)
),
)
.subcommand(
Command::new("history")
.about("Parses your history file and retrieves installations")
.arg(
Arg::new("history_file")
.value_name("PATH")
.help("Path to shell history file")
.required(true)
.value_parser(clap::value_parser!(Utf8PathBuf))
.action(ArgAction::Set)
)
.arg(
Arg::new("yes")
.short('y')
.long("yes")
.help("Don't prompt the user and select everything")
.action(ArgAction::SetTrue)
),
)
.subcommand(
Command::new("config")
.about("Provides options for managing configuration")
.arg(
Arg::new("new")
.short('n')
.long("new")
.help("Create a new config")
.action(ArgAction::SetTrue)
)
.arg(
Arg::new("path")
.short('p')
.long("path")
.help("Print out path to config")
.action(ArgAction::SetTrue)
),
)
.subcommand(
Command::new("bugreport")
.about("Collect and print information that can be send along with a bug report")
)
.get_matches();
let config_path: Utf8PathBuf = matches
.get_one("config-path")
.cloned()
.unwrap_or_else(Config::default_path);
match matches.subcommand() {
Some(("init", sub_m)) => {
let shell_name: &String = sub_m.get_one("shell").context("shell name is missing")?;
init::init_main(&config_path, shell_name)
}
Some(("catch", sub_m)) => {
let line: &String = sub_m.get_one("line").context("line is missing")?;
catch::catch(config_path, line).context("catching a command")
}
Some(("install", sub_m)) => {
install::install(config_path, sub_m.get_flag("yes")).context("installing packages")
}
Some(("clean", _)) => clean::clean(config_path).context("cleaning packages"),
Some(("history", sub_m)) => {
let hist_path: &PathBuf = sub_m
.get_one("history_file")
.context("path to history file is not provided")?;
history::history(config_path, hist_path, sub_m.get_flag("yes"))
.context("capturing history")
}
Some(("config", subm)) => {
if subm.get_flag("path") && !subm.get_flag("new") {
println!("Your config path is {config_path}");
Ok(())
} else {
let mut config = config::Config::new(config_path)?;
config.clone_repo_ask()?;
Ok(())
}
}
Some(("bugreport", _)) => {
bugreport!()
.info(SoftwareVersion::default())
.info(EnvironmentVariables::list(&["SHELL", "EMPLACE_CONFIG"]))
.info(CommandOutput::new("Git version", "git", &["--version"]))
.info(CompileTimeInformation::default())
.print::<Markdown>();
Ok(())
}
Some((other, _)) => Err(anyhow!("Unrecognized subcommand \"{}\"", other)),
None => Ok(()),
}
}
fn main() {
if let Err(err) = safe_main() {
error!("Critical Emplace error while {:?}", err);
}
}