use std::fs::File;
use clap::{Parser, Subcommand};
use regex_lite::Regex;
use takecrate::{
inst::{InstallConfig, PackageManifest},
manifest::{AppId, FileType},
};
use tracing::level_filters::LevelFilter;
pub fn main() -> anyhow::Result<()> {
init_logging()?;
let result = main2();
if let Err(error) = &result {
tracing::error!(?error, "main error");
}
result
}
fn main2() -> anyhow::Result<()> {
let manifest = create_app_package_manifest()?;
if is_installer() {
takecrate::install_interactive(&manifest)?;
return Ok(());
}
let args = Args::parse();
match &args.command {
Command::Hello => {
println!("Hello world!");
let manifest = takecrate::manifest(&manifest.app_id)?;
let content = std::fs::read_to_string(manifest.app_paths.data.join("test.txt"))?;
println!("test.txt: {content}");
}
Command::Self_(self_args) => match self_args.command {
SelfCommand::Install { quiet } => {
if quiet {
let config = InstallConfig::new_user()?;
takecrate::install(&manifest, &config)?;
} else {
takecrate::install_interactive(&manifest)?;
}
}
SelfCommand::Uninstall { quiet } => {
if quiet {
takecrate::uninstall(&manifest.app_id)?;
} else {
takecrate::uninstall_interactive(&manifest.app_id)?;
}
}
},
}
Ok(())
}
fn is_installer() -> bool {
if std::env::args_os().len() > 1 {
return false;
}
let name = std::env::current_exe().unwrap_or_default();
let name = if !std::env::consts::EXE_SUFFIX.is_empty() {
name.file_stem().unwrap_or(name.as_os_str())
} else {
name.as_os_str()
};
let name = name.to_string_lossy();
let pattern = Regex::new(r"(?i:[. _-]installer)$").unwrap();
pattern.is_match(&name)
}
fn init_logging() -> anyhow::Result<()> {
let log_filename = format!("takecrate_example_installer_{}.log", whoami::username());
let log_file = File::options()
.create(true)
.append(true)
.open(tempfile::env::temp_dir().join(log_filename))?;
tracing_subscriber::fmt()
.with_ansi(false)
.with_max_level(LevelFilter::TRACE)
.with_writer(log_file)
.init();
Ok(())
}
fn create_app_package_manifest() -> anyhow::Result<PackageManifest> {
let app_id = AppId::new("example.takecrate.takecrate-example-installer")?;
let mut manifest = PackageManifest::new(&app_id)
.with_self_exe_renamed("takecrate-example".to_string() + std::env::consts::EXE_SUFFIX)?
.with_interactive_uninstall_args(&["self", "uninstall"])
.with_quiet_uninstall_args(&["self", "uninstall", "--quiet"]);
manifest.app_metadata.display_name = "Takecrate Example Installer".to_string();
manifest.app_metadata.display_version = "1.0.0".to_string();
let manifest = manifest.with_file_entry("test.txt", FileType::Data)?;
Ok(manifest)
}
#[derive(Debug, Parser)]
#[command(version)]
struct Args {
#[command(subcommand)]
command: Command,
}
#[derive(Debug, Subcommand)]
enum Command {
Hello,
Self_(SelfArgs),
}
#[derive(Parser, Debug)]
struct SelfArgs {
#[command(subcommand)]
command: SelfCommand,
}
#[derive(Debug, Subcommand)]
enum SelfCommand {
Install {
#[arg(long)]
quiet: bool,
},
Uninstall {
#[arg(long)]
quiet: bool,
},
}