use std::ffi::OsString;
use std::fs::{self, File};
use std::path::PathBuf;
use anyhow::{Context, Result, anyhow};
use clap::Command;
use serde_json::json;
use crate::build::manpage;
use crate::output::action_result;
pub fn exec(
cli: Command,
target: Option<PathBuf>,
output_opt: Option<&str>,
) -> Result<()> {
let dest = match target {
Some(p) => p,
None => default_user_man_dir(
std::env::var_os("XDG_DATA_HOME"),
std::env::var_os("HOME"),
)?,
};
fs::create_dir_all(&dest).with_context(|| {
format!("failed to create destination directory {}", dest.display())
})?;
let path = dest.join("manta.1");
let mut f = File::create(&path)
.with_context(|| format!("failed to create {}", path.display()))?;
manpage::render_consolidated(cli, &mut f).with_context(|| {
format!("failed to render manta.1 into {}", path.display())
})?;
action_result::print_with_data(
&format!("Installed manta.1 to {}.", dest.display()),
&json!({"path": dest.to_string_lossy()}),
output_opt,
)?;
Ok(())
}
fn default_user_man_dir(
xdg_data_home: Option<OsString>,
home: Option<OsString>,
) -> Result<PathBuf> {
let base = xdg_data_home
.map(PathBuf::from)
.or_else(|| home.map(|h| PathBuf::from(h).join(".local").join("share")))
.ok_or_else(|| {
anyhow!(
"could not determine $XDG_DATA_HOME or $HOME; \
pass an explicit --path"
)
})?;
Ok(base.join("man").join("man1"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn xdg_data_home_takes_precedence_over_home() {
let p = default_user_man_dir(
Some("/tmp/xdg-test".into()),
Some("/Users/alice".into()),
)
.unwrap();
assert_eq!(p, PathBuf::from("/tmp/xdg-test/man/man1"));
}
#[test]
fn home_fallback_used_when_xdg_unset() {
let p = default_user_man_dir(None, Some("/Users/bob".into())).unwrap();
assert_eq!(p, PathBuf::from("/Users/bob/.local/share/man/man1"));
}
#[test]
fn error_when_both_unset() {
let r = default_user_man_dir(None, None);
assert!(r.is_err());
}
}