feat: add CLI asset generation for shell completions and man page
This commit is contained in:
Generated
+27
@@ -226,6 +226,15 @@ dependencies = [
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.5.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c757a3b7e39161a4e56f9365141ada2a6c915a8622c408ab6bb4b5d047371031"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.55"
|
||||
@@ -244,6 +253,16 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
|
||||
|
||||
[[package]]
|
||||
name = "clap_mangen"
|
||||
version = "0.2.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ea63a92086df93893164221ad4f24142086d535b3a0957b9b9bea2dc86301"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"roff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.4"
|
||||
@@ -369,6 +388,8 @@ dependencies = [
|
||||
"ar",
|
||||
"bzip2",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"clap_mangen",
|
||||
"fd-lock",
|
||||
"filetime",
|
||||
"flate2",
|
||||
@@ -1608,6 +1629,12 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roff"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3"
|
||||
|
||||
[[package]]
|
||||
name = "rpassword"
|
||||
version = "7.4.0"
|
||||
|
||||
@@ -37,6 +37,8 @@ petgraph = "0.8.3"
|
||||
fd-lock = "4.0.4"
|
||||
reqwest = { version = "0.13.2", default-features = false, features = ["blocking", "native-tls"] }
|
||||
filetime = "0.2.27"
|
||||
clap_complete = "4.5.66"
|
||||
clap_mangen = "0.2.31"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "=3.25.0"
|
||||
|
||||
@@ -19,6 +19,10 @@ Depot is a source-based package manager designed for Linux. It focuses on reprod
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
When installing via Meson (`meson install`), Depot now generates and installs:
|
||||
- Shell completions for Bash, Zsh, and Fish
|
||||
- A `depot(1)` man page
|
||||
|
||||
### Installing a Package
|
||||
|
||||
To install a package from a spec file:
|
||||
|
||||
+10
@@ -125,3 +125,13 @@ install_data(
|
||||
'contrib/README.md',
|
||||
install_dir: join_paths(get_option('datadir'), 'doc', meson.project_name()),
|
||||
)
|
||||
|
||||
meson.add_install_script(
|
||||
sh,
|
||||
join_paths(src_root, 'tools', 'meson', 'install-cli-assets.sh'),
|
||||
join_paths(build_root, 'depot'),
|
||||
join_paths(get_option('datadir'), 'bash-completion', 'completions'),
|
||||
join_paths(get_option('datadir'), 'zsh', 'site-functions'),
|
||||
join_paths(get_option('datadir'), 'fish', 'vendor_completions.d'),
|
||||
join_paths(get_option('mandir'), 'man1'),
|
||||
)
|
||||
|
||||
@@ -112,6 +112,13 @@ pub enum Commands {
|
||||
},
|
||||
/// Show current configuration
|
||||
Config,
|
||||
/// Generate shell completion scripts and a man page into an output directory.
|
||||
#[command(hide = true)]
|
||||
GenerateArtifacts {
|
||||
/// Output directory for generated files
|
||||
#[arg(long, value_name = "DIR")]
|
||||
out_dir: PathBuf,
|
||||
},
|
||||
/// Create a new package specification interactively
|
||||
MakeSpec {
|
||||
/// Output file path (defaults to <name>.toml)
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
//! Generation helpers for CLI man pages and shell completions.
|
||||
|
||||
use crate::cli::Cli;
|
||||
use anyhow::{Context, Result};
|
||||
use clap::CommandFactory;
|
||||
use clap_complete::Shell;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
const BIN_NAME: &str = "depot";
|
||||
|
||||
/// Generate all supported shell completion scripts and a man page into `out_dir`.
|
||||
pub fn generate_cli_assets(out_dir: &Path) -> Result<()> {
|
||||
fs::create_dir_all(out_dir)
|
||||
.with_context(|| format!("Failed to create output directory {}", out_dir.display()))?;
|
||||
|
||||
generate_completion(out_dir, Shell::Bash, "depot.bash")?;
|
||||
generate_completion(out_dir, Shell::Zsh, "_depot")?;
|
||||
generate_completion(out_dir, Shell::Fish, "depot.fish")?;
|
||||
generate_man_page(out_dir, "depot.1")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn command_for_generation() -> clap::Command {
|
||||
Cli::command().name(BIN_NAME)
|
||||
}
|
||||
|
||||
fn generate_completion(out_dir: &Path, shell: Shell, filename: &str) -> Result<()> {
|
||||
let mut command = command_for_generation();
|
||||
let output_path = out_dir.join(filename);
|
||||
let mut buffer = Vec::new();
|
||||
clap_complete::generate(shell, &mut command, BIN_NAME, &mut buffer);
|
||||
fs::write(&output_path, buffer).with_context(|| {
|
||||
format!(
|
||||
"Failed to write {} completion to {}",
|
||||
shell,
|
||||
output_path.display()
|
||||
)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_man_page(out_dir: &Path, filename: &str) -> Result<()> {
|
||||
let output_path = out_dir.join(filename);
|
||||
let mut buffer = Vec::new();
|
||||
clap_mangen::Man::new(command_for_generation())
|
||||
.render(&mut buffer)
|
||||
.context("Failed to render clap man page")?;
|
||||
fs::write(&output_path, buffer)
|
||||
.with_context(|| format!("Failed to write man page {}", output_path.display()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn generate_cli_assets_writes_expected_files() {
|
||||
let temp = tempfile::tempdir().unwrap();
|
||||
generate_cli_assets(temp.path()).unwrap();
|
||||
|
||||
let bash = temp.path().join("depot.bash");
|
||||
let zsh = temp.path().join("_depot");
|
||||
let fish = temp.path().join("depot.fish");
|
||||
let man = temp.path().join("depot.1");
|
||||
|
||||
assert!(bash.exists());
|
||||
assert!(zsh.exists());
|
||||
assert!(fish.exists());
|
||||
assert!(man.exists());
|
||||
assert!(!std::fs::read_to_string(&man).unwrap().is_empty());
|
||||
}
|
||||
}
|
||||
+6
-2
@@ -1,7 +1,7 @@
|
||||
use crate::cli::{Cli, Commands, RepoCommands, RepoKindArg};
|
||||
use crate::{
|
||||
builder, config, cross, db, deps, index, install, locking, package, planner, signing, source,
|
||||
staging, ui,
|
||||
builder, cli_assets, config, cross, db, deps, index, install, locking, package, planner,
|
||||
signing, source, staging, ui,
|
||||
};
|
||||
use anyhow::{Context, Result};
|
||||
use std::fs;
|
||||
@@ -1949,6 +1949,10 @@ pub fn run(cli: Cli) -> Result<()> {
|
||||
}
|
||||
}
|
||||
},
|
||||
Commands::GenerateArtifacts { out_dir } => {
|
||||
cli_assets::generate_cli_assets(&out_dir)?;
|
||||
ui::success(format!("Generated CLI assets in {}", out_dir.display()));
|
||||
}
|
||||
Commands::Config => {
|
||||
let config = config::Config::for_rootfs(&cli.rootfs);
|
||||
let config_lock = locking::open_lock(&config)?;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
mod builder;
|
||||
mod cli;
|
||||
mod cli_assets;
|
||||
mod commands;
|
||||
mod config;
|
||||
mod cross;
|
||||
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$#" -ne 5 ]; then
|
||||
echo "usage: $0 <depot-bin> <bash-dir> <zsh-dir> <fish-dir> <man1-dir>" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
depot_bin="$1"
|
||||
bash_dir="$2"
|
||||
zsh_dir="$3"
|
||||
fish_dir="$4"
|
||||
man1_dir="$5"
|
||||
|
||||
if [ ! -x "$depot_bin" ]; then
|
||||
echo "error: depot binary is not executable: $depot_bin" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${MESON_INSTALL_DESTDIR_PREFIX:-}" ]; then
|
||||
echo "error: MESON_INSTALL_DESTDIR_PREFIX is not set" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
resolve_dest() {
|
||||
case "$1" in
|
||||
/*) printf '%s%s\n' "${DESTDIR:-}" "$1" ;;
|
||||
*) printf '%s/%s\n' "$MESON_INSTALL_DESTDIR_PREFIX" "$1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
tmpdir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmpdir"' EXIT
|
||||
|
||||
"$depot_bin" generate-artifacts --out-dir "$tmpdir"
|
||||
|
||||
bash_dest="$(resolve_dest "$bash_dir")"
|
||||
zsh_dest="$(resolve_dest "$zsh_dir")"
|
||||
fish_dest="$(resolve_dest "$fish_dir")"
|
||||
man_dest="$(resolve_dest "$man1_dir")"
|
||||
|
||||
mkdir -p "$bash_dest" "$zsh_dest" "$fish_dest" "$man_dest"
|
||||
cp "$tmpdir/depot.bash" "$bash_dest/depot"
|
||||
cp "$tmpdir/_depot" "$zsh_dest/_depot"
|
||||
cp "$tmpdir/depot.fish" "$fish_dest/depot.fish"
|
||||
cp "$tmpdir/depot.1" "$man_dest/depot.1"
|
||||
Reference in New Issue
Block a user