storkit: merge 369_bug_cli_treats_help_and_version_as_project_paths
This commit is contained in:
@@ -34,6 +34,32 @@ use std::path::PathBuf;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
|
|
||||||
|
/// What the first CLI argument means.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
enum CliDirective {
|
||||||
|
/// `--help` / `-h`
|
||||||
|
Help,
|
||||||
|
/// `--version` / `-V`
|
||||||
|
Version,
|
||||||
|
/// An unrecognised flag (starts with `-`).
|
||||||
|
UnknownFlag(String),
|
||||||
|
/// A positional path argument.
|
||||||
|
Path,
|
||||||
|
/// No arguments at all.
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inspect the raw CLI arguments and return the directive they imply.
|
||||||
|
fn classify_cli_args(args: &[String]) -> CliDirective {
|
||||||
|
match args.first().map(String::as_str) {
|
||||||
|
None => CliDirective::None,
|
||||||
|
Some("--help" | "-h") => CliDirective::Help,
|
||||||
|
Some("--version" | "-V") => CliDirective::Version,
|
||||||
|
Some(a) if a.starts_with('-') => CliDirective::UnknownFlag(a.to_string()),
|
||||||
|
Some(_) => CliDirective::Path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolve the optional positional path argument (everything after the binary
|
/// Resolve the optional positional path argument (everything after the binary
|
||||||
/// name) into an absolute `PathBuf`. Returns `None` when no argument was
|
/// name) into an absolute `PathBuf`. Returns `None` when no argument was
|
||||||
/// supplied so that the caller can fall back to the auto-detect behaviour.
|
/// supplied so that the caller can fall back to the auto-detect behaviour.
|
||||||
@@ -53,8 +79,61 @@ async fn main() -> Result<(), std::io::Error> {
|
|||||||
|
|
||||||
// Collect CLI args, skipping the binary name (argv[0]).
|
// Collect CLI args, skipping the binary name (argv[0]).
|
||||||
let cli_args: Vec<String> = std::env::args().skip(1).collect();
|
let cli_args: Vec<String> = std::env::args().skip(1).collect();
|
||||||
|
|
||||||
|
// Handle CLI flags before treating anything as a project path.
|
||||||
|
match classify_cli_args(&cli_args) {
|
||||||
|
CliDirective::Help => {
|
||||||
|
println!("storkit [PATH]");
|
||||||
|
println!();
|
||||||
|
println!("Serve a storkit project.");
|
||||||
|
println!();
|
||||||
|
println!("USAGE:");
|
||||||
|
println!(" storkit [PATH]");
|
||||||
|
println!();
|
||||||
|
println!("ARGS:");
|
||||||
|
println!(
|
||||||
|
" PATH Path to an existing project directory. \
|
||||||
|
If omitted, storkit searches parent directories for a .storkit/ root."
|
||||||
|
);
|
||||||
|
println!();
|
||||||
|
println!("OPTIONS:");
|
||||||
|
println!(" -h, --help Print this help and exit");
|
||||||
|
println!(" -V, --version Print the version and exit");
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
CliDirective::Version => {
|
||||||
|
println!("storkit {}", env!("CARGO_PKG_VERSION"));
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
CliDirective::UnknownFlag(flag) => {
|
||||||
|
eprintln!("error: unknown option: {flag}");
|
||||||
|
eprintln!("Run 'storkit --help' for usage.");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
CliDirective::Path | CliDirective::None => {}
|
||||||
|
}
|
||||||
|
|
||||||
let explicit_path = parse_project_path_arg(&cli_args, &cwd);
|
let explicit_path = parse_project_path_arg(&cli_args, &cwd);
|
||||||
|
|
||||||
|
// When a path is given explicitly on the CLI, it must already exist as a
|
||||||
|
// directory. We do not create directories from the command line.
|
||||||
|
if let Some(ref path) = explicit_path {
|
||||||
|
if !path.exists() {
|
||||||
|
eprintln!(
|
||||||
|
"error: path does not exist: {}",
|
||||||
|
path.display()
|
||||||
|
);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
if !path.is_dir() {
|
||||||
|
eprintln!(
|
||||||
|
"error: path is not a directory: {}",
|
||||||
|
path.display()
|
||||||
|
);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(explicit_root) = explicit_path {
|
if let Some(explicit_root) = explicit_path {
|
||||||
// An explicit path was given on the command line.
|
// An explicit path was given on the command line.
|
||||||
// Open it directly — scaffold .storkit/ if it is missing — and
|
// Open it directly — scaffold .storkit/ if it is missing — and
|
||||||
@@ -399,6 +478,61 @@ name = "coder"
|
|||||||
.unwrap_or_else(|e| panic!("Invalid project.toml: {e}"));
|
.unwrap_or_else(|e| panic!("Invalid project.toml: {e}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── classify_cli_args ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classify_none_when_no_args() {
|
||||||
|
assert_eq!(classify_cli_args(&[]), CliDirective::None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classify_help_long() {
|
||||||
|
assert_eq!(
|
||||||
|
classify_cli_args(&["--help".to_string()]),
|
||||||
|
CliDirective::Help
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classify_help_short() {
|
||||||
|
assert_eq!(
|
||||||
|
classify_cli_args(&["-h".to_string()]),
|
||||||
|
CliDirective::Help
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classify_version_long() {
|
||||||
|
assert_eq!(
|
||||||
|
classify_cli_args(&["--version".to_string()]),
|
||||||
|
CliDirective::Version
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classify_version_short() {
|
||||||
|
assert_eq!(
|
||||||
|
classify_cli_args(&["-V".to_string()]),
|
||||||
|
CliDirective::Version
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classify_unknown_flag() {
|
||||||
|
assert_eq!(
|
||||||
|
classify_cli_args(&["--serve".to_string()]),
|
||||||
|
CliDirective::UnknownFlag("--serve".to_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classify_path() {
|
||||||
|
assert_eq!(
|
||||||
|
classify_cli_args(&["/some/path".to_string()]),
|
||||||
|
CliDirective::Path
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// ── parse_project_path_arg ────────────────────────────────────────────
|
// ── parse_project_path_arg ────────────────────────────────────────────
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user