use std::ffi::OsString;
use std::path::PathBuf;
use std::process::{Command, ExitCode};
use anyhow::Context;
use clap::{ArgMatches, Args};
use spacetimedb_paths::cli::BinFile;
use spacetimedb_paths::{FromPathUnchecked, RootDir, SpacetimePaths};
pub fn cli() -> clap::Command {
Version::augment_args(clap::Command::new("version"))
}
#[derive(clap::Args)]
#[command(disable_help_flag = true)]
struct Version {
#[arg(allow_hyphen_values = true, num_args = 0..)]
args: Vec<OsString>,
}
pub async fn exec(paths: &SpacetimePaths, root_dir: Option<&RootDir>, args: &ArgMatches) -> anyhow::Result<ExitCode> {
let args = args.get_many::<OsString>("args").unwrap_or_default();
let bin_path;
let bin_path = if let Some(artifact_dir) = running_from_target_dir() {
let update_path = artifact_dir
.join("spacetimedb-update")
.with_extension(std::env::consts::EXE_EXTENSION);
anyhow::ensure!(
update_path.exists(),
"running `spacetime version` from a target/ directory, but the spacetimedb-update
binary doesn't exist. try running `cargo build -p spacetimedb-update`"
);
bin_path = BinFile::from_path_unchecked(update_path);
&bin_path
} else {
&paths.cli_bin_file
};
let mut cmd = Command::new(bin_path);
if let Some(root_dir) = root_dir {
cmd.arg("--root-dir").arg(root_dir);
}
cmd.arg("version").args(args);
let applet = "spacetimedb-update";
#[cfg(unix)]
{
use std::os::unix::process::CommandExt;
cmd.arg0(applet);
}
#[cfg(windows)]
cmd.env("SPACETIMEDB_UPDATE_MULTICALL_APPLET", applet);
super::start::exec_replace(&mut cmd).with_context(|| format!("exec failed for {}", bin_path.display()))
}
fn running_from_target_dir() -> Option<PathBuf> {
let mut exe_path = std::env::current_exe().ok()?;
exe_path.pop();
let artifact_dir = exe_path;
let target_dir = artifact_dir
.ancestors()
.skip(1)
.take(2)
.find(|p| p.file_name() == Some("target".as_ref()))?;
target_dir
.parent()?
.join("Cargo.toml")
.try_exists()
.ok()
.map(|_| artifact_dir)
}