use std::fs;
use std::path::PathBuf;
use anyhow::Result;
use cargo_version_info::commands;
use cargo_version_info::commands::{
BadgeArgs,
BuildVersionArgs,
BumpArgs,
ChangedArgs,
ChangelogArgs,
CompareArgs,
CurrentArgs,
DevArgs,
DioxusArgs,
LatestArgs,
NextArgs,
PostBumpHookArgs,
PrLogArgs,
PreBumpHookArgs,
ReleasePageArgs,
RustToolchainArgs,
TagArgs,
UpdateReadmeArgs,
};
use clap::{
ArgAction,
CommandFactory,
Parser,
Subcommand,
};
#[derive(Parser, Debug)]
#[command(
bin_name = "cargo",
disable_version_flag = true,
arg_required_else_help = false
)]
struct CargoArgs {
#[arg(long = "tool-version", short = 'T')]
tool_version_flag: bool,
#[command(subcommand)]
subcmd: Option<TopCommand>,
}
#[derive(Subcommand, Debug)]
enum TopCommand {
#[command(name = "version-info")]
VersionInfo(VersionInfoCli),
}
#[derive(Parser, Debug)]
#[command(
disable_version_flag = true,
subcommand_required = false,
arg_required_else_help = false
)]
struct VersionInfoCli {
#[arg(long = "version", short = 'V', action = ArgAction::SetTrue)]
version_flag: bool,
#[command(subcommand)]
command: Option<VersionInfoCommand>,
#[arg(trailing_var_arg = true, hide = true)]
passthrough: Vec<String>,
}
#[derive(Parser, Debug)]
enum VersionInfoCommand {
#[command(name = "next")]
Next(NextArgs),
#[command(name = "current")]
Current(CurrentArgs),
#[command(name = "latest")]
Latest(LatestArgs),
#[command(name = "dev")]
Dev(DevArgs),
#[command(name = "tag")]
Tag(TagArgs),
#[command(name = "compare")]
Compare(CompareArgs),
#[command(name = "rust-toolchain")]
RustToolchain(RustToolchainArgs),
#[command(name = "dioxus")]
Dioxus(DioxusArgs),
#[command(name = "build-version")]
BuildVersion(BuildVersionArgs),
#[command(name = "changed")]
Changed(ChangedArgs),
#[command(name = "bump")]
Bump(BumpArgs),
#[command(name = "pre-bump-hook")]
PreBumpHook(PreBumpHookArgs),
#[command(name = "post-bump-hook")]
PostBumpHook(PostBumpHookArgs),
#[command(name = "changelog")]
Changelog(ChangelogArgs),
#[command(name = "pr-log")]
PrLog(PrLogArgs),
#[command(name = "release-page")]
ReleasePage(ReleasePageArgs),
#[command(name = "badge")]
Badge(BadgeArgs),
#[command(name = "update-readme")]
UpdateReadme(UpdateReadmeArgs),
#[command(name = "version")]
Version,
}
fn has_env_files() -> bool {
let current_dir = match std::env::current_dir() {
Ok(dir) => dir,
Err(_) => return false,
};
let patterns = [".env", ".env.local", ".env.prod", ".env.dev", ".env.test"];
for pattern in &patterns {
let path = current_dir.join(pattern);
if path.exists() && fs::metadata(&path).map(|m| m.is_file()).unwrap_or(false) {
return true;
}
}
if let Ok(user) = std::env::var("USER") {
let user_env = format!(".env.{}", user);
let path = current_dir.join(user_env);
if path.exists() && fs::metadata(&path).map(|m| m.is_file()).unwrap_or(false) {
return true;
}
}
false
}
fn main() -> Result<()> {
if has_env_files()
&& let Err(e) = dotenvage::EnvLoader::new().and_then(|loader| loader.load())
{
eprintln!("Warning: Failed to load/decrypt env files: {}", e);
eprintln!("Continuing with existing environment variables...");
}
let args = CargoArgs::parse();
if args.tool_version_flag {
return commands::build_version_for_repo(PathBuf::from(env!("CARGO_MANIFEST_DIR")));
}
if let Some(TopCommand::VersionInfo(cli)) = args.subcmd {
if cli.version_flag {
return commands::build_version_default();
}
if let Some(command) = cli.command {
return match command {
VersionInfoCommand::Next(args) => commands::next(args),
VersionInfoCommand::Current(args) => commands::current(args),
VersionInfoCommand::Latest(args) => commands::latest(args),
VersionInfoCommand::Dev(args) => commands::dev(args),
VersionInfoCommand::Tag(args) => commands::tag(args),
VersionInfoCommand::Compare(args) => commands::compare(args),
VersionInfoCommand::RustToolchain(args) => commands::rust_toolchain(args),
VersionInfoCommand::Dioxus(args) => commands::dioxus(args),
VersionInfoCommand::BuildVersion(args) => commands::build_version(args),
VersionInfoCommand::Changed(args) => commands::changed(args),
VersionInfoCommand::Bump(args) => commands::bump(args),
VersionInfoCommand::PreBumpHook(args) => commands::pre_bump_hook(args),
VersionInfoCommand::PostBumpHook(args) => commands::post_bump_hook(args),
VersionInfoCommand::Changelog(args) => commands::changelog(args),
VersionInfoCommand::PrLog(args) => commands::pr_log(args),
VersionInfoCommand::ReleasePage(args) => commands::release_page(args),
VersionInfoCommand::Badge(args) => commands::badge(args),
VersionInfoCommand::UpdateReadme(args) => commands::update_readme(args),
VersionInfoCommand::Version => commands::build_version_default(),
};
}
if cli
.passthrough
.iter()
.any(|arg| arg == "--version" || arg == "-V")
{
return commands::build_version_default();
}
if cli
.passthrough
.iter()
.any(|arg| arg == "--tool-version" || arg == "-T")
{
return commands::build_version_for_repo(PathBuf::from(env!("CARGO_MANIFEST_DIR")));
}
VersionInfoCli::command().print_help()?;
println!();
return Ok(());
}
CargoArgs::command().print_help()?;
println!();
Ok(())
}