diff --git a/bin/main.rs b/bin/main.rs index df10a26a..82df7669 100644 --- a/bin/main.rs +++ b/bin/main.rs @@ -3,19 +3,27 @@ mod terminal; use std::ffi::OsString; use std::io; +use std::io::Write; use std::{iter, process}; use anyhow::anyhow; -use radicle::version; +use radicle::version::Version; use radicle_term as term; use commands::*; pub const NAME: &str = "rad-tui"; -pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const DESCRIPTION: &str = "Radicle terminal interfaces"; +pub const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); pub const GIT_HEAD: &str = env!("GIT_HEAD"); +pub const TIMESTAMP: &str = env!("GIT_COMMIT_TIME"); +pub const VERSION: Version = Version { + name: NAME, + version: PKG_VERSION, + commit: GIT_HEAD, + timestamp: TIMESTAMP, +}; #[derive(Debug)] enum Command { @@ -65,18 +73,21 @@ fn parse_args() -> anyhow::Result { } fn print_help() -> anyhow::Result<()> { - version::print(&mut io::stdout(), NAME, VERSION, GIT_HEAD)?; + VERSION.write(&mut io::stdout())?; println!("{DESCRIPTION}"); println!(); - tui_help::run(Default::default(), terminal::profile) + tui_help::run(Default::default(), terminal::DefaultContext) } fn run(command: Command) -> Result<(), Option> { match command { Command::Version => { - version::print(&mut io::stdout(), NAME, VERSION, GIT_HEAD) + let mut stdout = io::stdout(); + VERSION + .write_json(&mut stdout) .map_err(|e| Some(e.into()))?; + writeln!(&mut stdout).ok(); } Command::Help => { print_help()?; diff --git a/bin/terminal.rs b/bin/terminal.rs index 9b0b438b..b728e005 100644 --- a/bin/terminal.rs +++ b/bin/terminal.rs @@ -8,26 +8,44 @@ pub use args::{Args, Error, Help}; use radicle_term as term; -use radicle::profile::Profile; +use radicle::profile::{Home, Profile}; /// Context passed to all commands. pub trait Context { /// Return the currently active profile, or an error if no profile is active. fn profile(&self) -> Result; + /// Return the Radicle home. + fn home(&self) -> Result; } impl Context for Profile { fn profile(&self) -> Result { Ok(self.clone()) } + + fn home(&self) -> Result { + Ok(self.home.clone()) + } } -impl Context for F -where - F: Fn() -> Result, -{ +pub struct DefaultContext; + +impl Context for DefaultContext { + fn home(&self) -> Result { + radicle::profile::home() + } + fn profile(&self) -> Result { - self() + match Profile::load() { + Ok(profile) => Ok(profile), + Err(radicle::profile::Error::NotFound(path)) => Err(args::Error::WithHint { + err: anyhow::anyhow!("Radicle profile not found in '{}'.", path.display()), + hint: "To setup your radicle profile, run `rad auth`.", + } + .into()), + Err(radicle::profile::Error::Config(e)) => Err(e.into()), + Err(e) => Err(anyhow::anyhow!("Could not load radicle profile: {e}")), + } } } @@ -49,7 +67,7 @@ where pub fn run_command_args(help: Help, cmd: C, args: Vec) -> ! where A: Args, - C: Command anyhow::Result>, + C: Command, { let options = match A::from_args(args) { Ok((opts, unparsed)) => { @@ -88,7 +106,7 @@ where } }; - match cmd.run(options, self::profile) { + match cmd.run(options, DefaultContext) { Ok(()) => process::exit(0), Err(err) => { fail(help.name, &err); diff --git a/build.rs b/build.rs index ddda179f..7b84b510 100644 --- a/build.rs +++ b/build.rs @@ -18,6 +18,23 @@ fn main() { }) .unwrap_or_else(|| String::from("unknown")); + // Set a build-time `GIT_COMMIT_TIME` env var which includes the commit time. + let commit_time = Command::new("git") + .arg("show") + .arg("--format=%ct") + .arg("HEAD") + .output() + .ok() + .and_then(|output| { + if output.status.success() { + String::from_utf8(output.stdout).ok() + } else { + None + } + }) + .unwrap_or(0.to_string()); + + println!("cargo:rustc-env=GIT_COMMIT_TIME={commit_time}"); println!("cargo:rustc-env=GIT_HEAD={hash}"); println!("cargo:rustc-rerun-if-changed=.git/HEAD"); }