shitbox/src/cmd/bootstrap/mod.rs

129 lines
4.2 KiB
Rust
Raw Normal View History

use crate::cmd;
2022-12-20 18:35:45 -05:00
use clap::{value_parser, Arg, ArgMatches, Command};
use clap_mangen::Man;
use std::{fs, io, path::PathBuf, process};
const programs: [&str; 8] = [
"shitbox",
"bootstrap",
"echo",
"false",
"head",
"hostname",
"true",
"sleep",
];
2022-12-20 12:05:21 -05:00
2022-12-20 18:35:45 -05:00
#[must_use]
2022-12-20 12:05:21 -05:00
pub fn cli() -> Command {
Command::new("bootstrap")
.version(env!("CARGO_PKG_VERSION"))
.author("Nathan Fisher")
.about("Install shitbox into the filesystem")
.long_about("Install symlinks, manpages and shell completions")
.args([
Arg::new("prefix")
.help("The directory path under which to install")
.short('p')
.long("prefix")
.num_args(1)
.default_value("/")
.required(false),
Arg::new("usr")
.help("Use /usr")
.long_help(
"Split the installation so that some applets go into /bin | /sbin\n\
while others are placed into /usr/bin | /usr/sbin",
)
.short('u')
.long("usr")
.default_value("true")
.value_parser(value_parser!(bool)),
])
.subcommands([
Command::new("all").about("Install everything"),
Command::new("links")
.about("Install links for each applet")
.arg(
Arg::new("soft")
.help("Install soft links instead of hardlinks")
.short('s')
.long("soft"),
),
Command::new("manpages")
.about("Install Unix man pages")
.alias("man"),
Command::new("completions")
.about("Install shell completions")
.alias("comp")
.args([
Arg::new("all")
.help("Install completions for all supported shells")
.short('a')
.long("all"),
Arg::new("bash")
.help("Bash shell completions")
.short('b')
.long("bash"),
Arg::new("fish")
.help("Fish shell completions")
.short('f')
.long("fish"),
Arg::new("nu")
.help("Nushell completions")
.short('n')
.long("nu"),
Arg::new("pwsh")
.help("PowerShell completions")
.short('p')
.long("pwsh"),
]),
])
}
fn manpage(prefix: &str, cmd: &str) -> Result<(), io::Error> {
let (fname, cmd) = match cmd {
"shitbox" => ("shitbox.1", crate::cli::cli()),
"bootstrap" => ("shitbox-bootstrap.1", cli()),
"echo" => ("echo.1", cmd::echo::cli()),
"false" => ("false.1", cmd::r#false::cli()),
"head" => ("head.1", cmd::head::cli()),
"hostname" => ("hostname.1", cmd::hostname::cli()),
"true" => ("true.1", cmd::r#true::cli()),
"sleep" => ("sleep.1", cmd::sleep::cli()),
_ => unimplemented!(),
};
let outdir: PathBuf = [prefix, "usr", "share", "man", "man1"].iter().collect();
if !outdir.exists() {
fs::create_dir_all(&outdir)?;
}
let mut outfile = outdir;
outfile.push(fname);
let man = Man::new(cmd);
let mut buffer: Vec<u8> = vec![];
man.render(&mut buffer)?;
fs::write(&outfile, buffer)?;
println!(" {}", outfile.display());
Ok(())
}
fn manpages(prefix: &str) -> Result<(), io::Error> {
println!("Generating Unix man pages:");
programs.iter().try_for_each(|cmd| manpage(prefix, cmd))?;
Ok(())
}
pub fn run(matches: &ArgMatches) {
if let Some(prefix) = matches.get_one::<String>("prefix") {
match matches.subcommand() {
Some(("manpages", _matches)) => {
if let Err(e) = manpages(&prefix) {
eprintln!("{e}");
process::exit(1);
}
}
_ => {}
}
}
}