Return errors from subcommands
This pulls in `anyhow` and updates subcommand implementations to return
results which propagate up to main.
Change-Id: Idd360e03c1adf8960c09a2690bf5e0753ac3e464
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/qg/+/119870
Commit-Queue: Alexei Frolov <frolv@google.com>
Reviewed-by: Erik Gilling <konkers@google.com>
diff --git a/Cargo.lock b/Cargo.lock
index 79929bf..51ba387 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1259,6 +1259,7 @@
name = "qg-cli"
version = "0.1.0"
dependencies = [
+ "anyhow",
"clap 4.0.26",
"qg",
"tokio",
diff --git a/qg-cli/Cargo.toml b/qg-cli/Cargo.toml
index 46f8f2d..315008c 100644
--- a/qg-cli/Cargo.toml
+++ b/qg-cli/Cargo.toml
@@ -8,6 +8,7 @@
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+anyhow = "1.0.66"
clap = { version = "4.0.25", features = ["derive"] }
qg = { path = "../qg" }
tokio = { version = "1.21.2", features = ["full"] }
diff --git a/qg-cli/src/main.rs b/qg-cli/src/main.rs
index 060cbcf..b3b8d55 100644
--- a/qg-cli/src/main.rs
+++ b/qg-cli/src/main.rs
@@ -13,17 +13,19 @@
// the License.
mod hello;
+mod new;
mod subcommands;
#[cfg(feature = "python")]
mod py_demo;
+use anyhow::Result;
use clap::{FromArgMatches, Subcommand};
use subcommands::Subcommands;
#[tokio::main]
-async fn main() {
+async fn main() -> Result<()> {
let app = clap::Command::new("qg");
let app = Subcommands::augment_subcommands(app);
@@ -34,6 +36,7 @@
Ok(subcommands) => subcommands.run(),
Err(e) if e.kind() == clap::error::ErrorKind::MissingSubcommand => {
run_main_command(&matches);
+ Ok(())
}
Err(e) => e.exit(),
}
diff --git a/qg-cli/src/new.rs b/qg-cli/src/new.rs
new file mode 100644
index 0000000..d645b60
--- /dev/null
+++ b/qg-cli/src/new.rs
@@ -0,0 +1,22 @@
+// Copyright 2022 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+use anyhow::{anyhow, Result};
+
+#[derive(clap::Parser, Debug)]
+pub struct Command {}
+
+pub fn run(_args: &Command) -> Result<()> {
+ Err(anyhow!("Not implemented"))
+}
diff --git a/qg-cli/src/subcommands.rs b/qg-cli/src/subcommands.rs
index b33cd98..aa3b870 100644
--- a/qg-cli/src/subcommands.rs
+++ b/qg-cli/src/subcommands.rs
@@ -12,7 +12,9 @@
// License for the specific language governing permissions and limitations under
// the License.
-use crate::hello;
+use anyhow::Result;
+
+use crate::{hello, new};
#[cfg(feature = "python")]
use crate::py_demo;
@@ -24,21 +26,28 @@
#[derive(clap::Parser, Debug)]
pub enum Subcommands {
Hello(hello::Command),
+ New(new::Command),
+
#[cfg(feature = "python")]
PyDemo(py_demo::Command),
}
impl Subcommands {
/// Invokes a subcommand with its parsed arguments.
- pub fn run(&self) {
+ pub fn run(&self) -> Result<()> {
match self {
- Self::Hello(cmd) => {
- hello::run(cmd);
+ Self::Hello(args) => {
+ hello::run(args);
+ }
+ Self::New(args) => {
+ new::run(args)?;
}
#[cfg(feature = "python")]
Self::PyDemo(cmd) => {
py_demo::run(cmd);
}
- }
+ };
+
+ Ok(())
}
}