Fix return code of --help and --version on cli

pull/218/head
Chip Senkbeil 11 months ago
parent 9bc50886bb
commit e0b8769087
No known key found for this signature in database
GPG Key ID: 35EF1F8EC72A4131

@ -13,6 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
requirement. This technically applied to v0.20.0-alpha.11, but wasn't caught requirement. This technically applied to v0.20.0-alpha.11, but wasn't caught
until the dependency updated until the dependency updated
### Fixed
- `distant --help` will now return exit code of 0
- `distant --version` will now return exit code of 0
## [0.20.0-alpha.11] ## [0.20.0-alpha.11]
### Added ### Added

@ -1,6 +1,6 @@
use std::ffi::OsString; use std::ffi::OsString;
use crate::options::DistantSubcommand; use crate::options::{DistantSubcommand, OptionsError};
use crate::{CliResult, Options}; use crate::{CliResult, Options};
mod commands; mod commands;
@ -18,12 +18,12 @@ pub struct Cli {
impl Cli { impl Cli {
/// Creates a new CLI instance by parsing command-line arguments /// Creates a new CLI instance by parsing command-line arguments
pub fn initialize() -> anyhow::Result<Self> { pub fn initialize() -> Result<Self, OptionsError> {
Self::initialize_from(std::env::args_os()) Self::initialize_from(std::env::args_os())
} }
/// Creates a new CLI instance by parsing providing arguments /// Creates a new CLI instance by parsing providing arguments
pub fn initialize_from<I, T>(args: I) -> anyhow::Result<Self> pub fn initialize_from<I, T>(args: I) -> Result<Self, OptionsError>
where where
I: IntoIterator<Item = T>, I: IntoIterator<Item = T>,
T: Into<OsString> + Clone, T: Into<OsString> + Clone,

@ -6,6 +6,7 @@ pub struct ReadmeDoctests;
use std::process::{ExitCode, Termination}; use std::process::{ExitCode, Termination};
use clap::error::ErrorKind;
use derive_more::{Display, Error, From}; use derive_more::{Display, Error, From};
mod cli; mod cli;
@ -16,7 +17,7 @@ mod options;
pub mod win_service; pub mod win_service;
pub use cli::Cli; pub use cli::Cli;
pub use options::Options; pub use options::{Options, OptionsError};
/// Wrapper around a [`CliResult`] that provides [`Termination`] support /// Wrapper around a [`CliResult`] that provides [`Termination`] support
pub struct MainResult(CliResult); pub struct MainResult(CliResult);
@ -31,6 +32,29 @@ impl From<CliResult> for MainResult {
} }
} }
impl From<OptionsError> for MainResult {
fn from(x: OptionsError) -> Self {
Self(match x {
OptionsError::Config(x) => Err(CliError::Error(x)),
OptionsError::Options(x) => match x.kind() {
// --help and --version should not actually exit with an error and instead display
// their related information while succeeding
ErrorKind::DisplayHelp | ErrorKind::DisplayVersion => {
// NOTE: We're causing a side effect here in constructing the main result,
// but seems cleaner than returning an error with an exit code of 0
// and a message to try to print. Plus, we leverage automatic color
// handling in this approach.
let _ = x.print();
Ok(())
}
// Everything else is an actual error and should fail
_ => Err(CliError::Error(anyhow::anyhow!(x))),
},
})
}
}
impl From<anyhow::Error> for MainResult { impl From<anyhow::Error> for MainResult {
fn from(x: anyhow::Error) -> Self { fn from(x: anyhow::Error) -> Self {
Self(Err(CliError::Error(x))) Self(Err(CliError::Error(x)))

@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};
use clap::builder::TypedValueParser as _; use clap::builder::TypedValueParser as _;
use clap::{Args, Parser, Subcommand, ValueEnum, ValueHint}; use clap::{Args, Parser, Subcommand, ValueEnum, ValueHint};
use clap_complete::Shell as ClapCompleteShell; use clap_complete::Shell as ClapCompleteShell;
use derive_more::IsVariant; use derive_more::{Display, Error, From, IsVariant};
use distant_core::net::common::{ConnectionId, Destination, Map, PortRange}; use distant_core::net::common::{ConnectionId, Destination, Map, PortRange};
use distant_core::net::server::Shutdown; use distant_core::net::server::Shutdown;
use distant_core::protocol::ChangeKind; use distant_core::protocol::ChangeKind;
@ -36,14 +36,24 @@ pub struct Options {
pub command: DistantSubcommand, pub command: DistantSubcommand,
} }
/// Represents an error associated with parsing options.
#[derive(Debug, Display, From, Error)]
pub enum OptionsError {
// When configuration file fails to load
Config(#[error(not(source))] anyhow::Error),
// When parsing options fails (or is something like --version or --help)
Options(#[error(not(source))] clap::Error),
}
impl Options { impl Options {
/// Creates a new CLI instance by parsing command-line arguments /// Creates a new CLI instance by parsing command-line arguments
pub fn load() -> anyhow::Result<Self> { pub fn load() -> Result<Self, OptionsError> {
Self::load_from(std::env::args_os()) Self::load_from(std::env::args_os())
} }
/// Creates a new CLI instance by parsing providing arguments /// Creates a new CLI instance by parsing providing arguments
pub fn load_from<I, T>(args: I) -> anyhow::Result<Self> pub fn load_from<I, T>(args: I) -> Result<Self, OptionsError>
where where
I: IntoIterator<Item = T>, I: IntoIterator<Item = T>,
T: Into<OsString> + Clone, T: Into<OsString> + Clone,

Loading…
Cancel
Save