#![deny(warnings, missing_docs, clippy::todo, clippy::unimplemented)]
#![allow(async_fn_in_trait)]
use clap::Parser;
use dirs::{cache_dir, config_dir, data_local_dir};
use mimalloc::MiMalloc;
use std::path::PathBuf;
pub use depl::*;
use crate::actions::{cat_action, edit_action, list_actions, new_action, remove_action};
use crate::cmd::{CatType, Cli, DeployerExecType, EditType, ExportType, ImportType, ListType, NewType, RemoveType};
use crate::entities::runs::Runs;
use crate::entities::skipper::Skipper;
use crate::globals::DeployerGlobalConfig;
use crate::pipelines::{
assign_pipeline_to_project, cat_pipeline, check_project_pipeline, edit_pipeline, export_project_pipeline,
list_pipelines, new_pipeline, remove_pipeline,
};
use crate::project::DeployerProjectOptions;
use crate::project::{cat_project, clean_runs, edit_project, init_project};
use crate::remote::{cat_remote, edit_remote, list_remote, new_remote, remove_remote};
use crate::rw::{VERBOSE, read, read_versioned, write, write_merge};
use crate::storage::{list_content, new_content, remove_content, use_content};
use crate::tui::docs;
use crate::cd::cd;
use crate::run::run;
use crate::watch::watch;
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
#[cfg(not(unix))]
compile_error!("`deployer` can't work with non-Unix systems.");
#[tokio::main(flavor = "current_thread")]
async fn main() {
std::panic::set_hook(Box::new(|e| {
let err = e
.to_string()
.replace("called `Result::unwrap()` on an `Err` value: ", "");
eprintln!("{}", err.trim());
std::process::exit(1);
}));
depl::install_ctrlc_handler().unwrap();
let args = Cli::parse();
VERBOSE.set(args.verbose).unwrap();
let cache_folder = if let Some(cache_folder) = &args.cache_folder {
let cf = PathBuf::from(cache_folder);
if cf.is_absolute() {
cf
} else {
let path = PathBuf::new();
path.join(cf)
}
} else {
cache_dir().expect("Can't get `cache` directory's location automatically, please specify one.")
};
let config_folder = if let Some(config_folder) = &args.config_folder {
let cf = PathBuf::from(config_folder);
if cf.is_absolute() {
cf
} else {
let path = PathBuf::new();
path.join(cf)
}
} else {
config_dir().expect("Can't get `config` directory's location automatically, please specify one.")
};
let storage_folder = if let Some(storage_folder) = &args.storage_folder {
let sf = PathBuf::from(storage_folder);
if sf.is_absolute() {
sf
} else {
let path = PathBuf::new();
path.join(sf)
}
} else {
data_local_dir().expect("Can't get `storage` directory's location automatically, please specify one.")
};
let mut globals = read_versioned::<DeployerGlobalConfig>(
&config_folder,
GLOBAL_CONF,
crate::globals::get_default_global_conf_version(),
);
DeployerGlobalConfig::make_sure_contain_defaults(&mut globals.actions_registry);
let config_path = args.config.as_deref().unwrap_or(PROJECT_CONF);
let mut config = read_versioned::<DeployerProjectOptions>(
&std::env::current_dir().unwrap(),
config_path,
crate::project::get_default_project_conf_version(),
);
config.version = crate::project::get_default_project_conf_version();
let mut runs = read::<Runs>(&cache_folder, BUILD_CACHE_LIST);
let r#type = args.r#type.unwrap_or(DeployerExecType::Run(Default::default()));
match r#type {
DeployerExecType::Ls(ListType::Actions) => list_actions(&globals),
DeployerExecType::New(NewType::Action(args)) => {
let _ = new_action(&mut globals, &args).unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
}
DeployerExecType::Cat(CatType::Action(args)) => cat_action(&globals, args).unwrap(),
DeployerExecType::Edit(EditType::Action(args)) => {
edit_action(&mut globals, args).await.unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
}
DeployerExecType::Rm(RemoveType::Action(args)) => {
remove_action(&mut globals, args).unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
}
DeployerExecType::Ls(ListType::Pipelines) => list_pipelines(&globals).unwrap(),
DeployerExecType::New(NewType::Pipeline(args)) => {
new_pipeline(&mut globals, &args).unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
}
DeployerExecType::Cat(CatType::Pipeline(args)) => cat_pipeline(&globals, args).unwrap(),
DeployerExecType::Edit(EditType::Pipeline(args)) => {
edit_pipeline(&mut globals, args).await.unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
}
DeployerExecType::Rm(RemoveType::Pipeline(args)) => {
remove_pipeline(&mut globals, args).unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
}
DeployerExecType::Export(ExportType::Registries(args)) => {
globals.export_registries(&args.output).unwrap();
}
DeployerExecType::Import(ImportType::Registries(args)) => {
globals.import_registries(&args.input).unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
}
DeployerExecType::Ls(ListType::Content(args)) => list_content(&storage_folder, args).unwrap(),
DeployerExecType::New(NewType::Content(args)) => new_content(&storage_folder, args).unwrap(),
DeployerExecType::Rm(RemoveType::Content(args)) => remove_content(&storage_folder, args).unwrap(),
DeployerExecType::Ls(ListType::Remote) => list_remote(&globals),
DeployerExecType::New(NewType::Remote(args)) => {
let _ = new_remote(&mut globals, args).unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
}
DeployerExecType::Cat(CatType::Remote(args)) => cat_remote(&globals, args).unwrap(),
DeployerExecType::Edit(EditType::Remote(args)) => {
edit_remote(&mut globals, args).unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
}
DeployerExecType::Rm(RemoveType::Remote(args)) => {
remove_remote(&mut globals, args).unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
}
DeployerExecType::Init => {
init_project(&mut globals, &mut config).unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
write(std::env::current_dir().unwrap(), config_path, &config);
}
DeployerExecType::With(args) => {
assign_pipeline_to_project(&mut globals, &mut config, &args).unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
write(std::env::current_dir().unwrap(), config_path, &config);
}
DeployerExecType::Cat(CatType::Project(args)) => cat_project(&config, args).unwrap(),
DeployerExecType::Export(ExportType::Pipeline(args)) => {
export_project_pipeline(&config, &globals, &cache_folder, &config_folder, &storage_folder, args)
.await
.unwrap()
}
DeployerExecType::Edit(EditType::Project) => {
edit_project(&mut globals, &mut config).await.unwrap();
write(&config_folder, GLOBAL_CONF, &globals);
write(std::env::current_dir().unwrap(), config_path, &config);
}
DeployerExecType::Check(args) => {
check_project_pipeline(&config, &globals, &cache_folder, &config_folder, &storage_folder, args).await;
}
DeployerExecType::Run(args) => {
if !args.no_clear {
clearscreen::clear().expect("Failed to clear screen");
}
let skipper = Skipper::new(args.skip.unwrap_or(0usize));
let success = run(
&config,
&globals,
&mut runs,
&cache_folder,
&config_folder,
&storage_folder,
&args,
None,
skipper,
None,
)
.await
.unwrap();
write_merge(&cache_folder, BUILD_CACHE_LIST, &runs);
if !success {
std::process::exit(1);
}
}
DeployerExecType::Watch(args) => {
watch(
&config,
&globals,
&mut runs,
&cache_folder,
&config_folder,
&storage_folder,
&args,
)
.await
.unwrap();
write_merge(&cache_folder, BUILD_CACHE_LIST, &runs);
}
DeployerExecType::Clean(args) => {
clean_runs(&config, &mut runs, &cache_folder, &args).unwrap();
write(&cache_folder, BUILD_CACHE_LIST, &runs);
}
DeployerExecType::Cd(args) => {
cd(&config, &runs, &args).await.unwrap();
}
DeployerExecType::Use(args) => use_content(&storage_folder, args).unwrap(),
DeployerExecType::Docs => docs::read_docs().unwrap(),
DeployerExecType::Migrations => docs::read_migrations().unwrap(),
}
}