scaffold: CLI surface with stubbed kernel and patch verbs
Add the spectral command tree -- kernel quest/test and patch check/format/commit/create/submit/update -- with every verb wired through main to a todo!() body, plus the pieces they will share: - config: resolve the kernel tree from $SPECTRAL_KERNEL, falling back to ~/.spectral/linux, patches under ~/.spectral/patches, and confirm a tree really is one before anything uses it - git: a thin wrapper over the git binary, currently only run - error: one thiserror enum, converted once in main - patch/checkpatch and patch/maintainers: seams around the tree's own scripts/checkpatch.pl and scripts/get_maintainer.pl, so spectral never carries a stale copy of the kernel's rules 20 functions are todo!(); the #[allow(dead_code)] sites mark the items that are unreachable only until their caller is written. fmt, clippy -D warnings, and test are all clean.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
//! One error type for the whole CLI.
|
||||
//!
|
||||
//! Anything that can go wrong ends up as an [`Error`], gets a `?` at the call
|
||||
//! site, and is printed once in `main` — no `unwrap` in the command paths.
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Shorthand for the crate's result type.
|
||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
|
||||
// Variants that no command constructs yet, but that the command paths below
|
||||
// are written to return. Safe to drop the allow once they are all reached.
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
/// Nothing at the configured path at all.
|
||||
#[error("no kernel tree at `{path}`; set ${env} or clone one there")]
|
||||
KernelTreeMissing { path: PathBuf, env: &'static str },
|
||||
|
||||
/// Something is there, but it is not a kernel source tree.
|
||||
#[error("`{path}` is not a kernel source tree (no scripts/checkpatch.pl)")]
|
||||
NotAKernelTree { path: PathBuf },
|
||||
|
||||
/// An external tool ran and failed.
|
||||
#[error("`{program} {args}` failed (exit {code}):\n{stderr}")]
|
||||
ExternalCommand {
|
||||
program: String,
|
||||
args: String,
|
||||
code: String,
|
||||
stderr: String,
|
||||
},
|
||||
|
||||
/// An external tool could not even be started.
|
||||
#[error("could not run `{program}`")]
|
||||
CommandSpawn {
|
||||
program: String,
|
||||
#[source]
|
||||
source: std::io::Error,
|
||||
},
|
||||
|
||||
/// A patch file the user named does not exist.
|
||||
#[error("no patch named `{name}` in `{dir}`")]
|
||||
PatchNotFound { name: String, dir: PathBuf },
|
||||
|
||||
#[error(transparent)]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
Http(#[from] reqwest::Error),
|
||||
}
|
||||
Reference in New Issue
Block a user