cargo_subcommand/
error.rs

1use glob::{GlobError, PatternError};
2use std::fmt::{Display, Formatter, Result as FmtResult};
3use std::io::Error as IoError;
4use std::path::PathBuf;
5use toml::de::Error as TomlError;
6
7#[derive(Debug)]
8pub enum Error {
9    InvalidArgs,
10    ManifestNotAWorkspace,
11    ManifestNotFound,
12    RustcNotFound,
13    ManifestPathNotFound,
14    GlobPatternError(&'static str),
15    Glob(GlobError),
16    UnexpectedWorkspace(PathBuf),
17    NoPackageInManifest(PathBuf),
18    PackageNotFound(PathBuf, String),
19    ManifestNotInWorkspace {
20        manifest: PathBuf,
21        workspace_manifest: PathBuf,
22    },
23    Io(PathBuf, IoError),
24    Toml(PathBuf, TomlError),
25    BinNotFound(String),
26    ExampleNotFound(String),
27    DuplicateBin(String),
28    DuplicateExample(String),
29}
30
31pub type Result<T, E = Error> = std::result::Result<T, E>;
32
33impl Display for Error {
34    fn fmt(&self, f: &mut Formatter) -> FmtResult {
35        f.write_str(match self {
36            Self::InvalidArgs => "Invalid args.",
37            Self::ManifestNotAWorkspace => {
38                "The provided Cargo.toml does not contain a `[workspace]`"
39            }
40            Self::ManifestNotFound => "Didn't find Cargo.toml.",
41            Self::ManifestPathNotFound => "The manifest-path must be a path to a Cargo.toml file",
42            Self::RustcNotFound => "Didn't find rustc.",
43            Self::GlobPatternError(error) => error,
44            Self::Glob(error) => return error.fmt(f),
45            Self::UnexpectedWorkspace(path) => {
46                return write!(f, "Did not expect a `[workspace]` at `{}`", path.display())
47            }
48            Self::NoPackageInManifest(manifest) => {
49                return write!(
50                    f,
51                    "Failed to parse manifest at `{}`: virtual manifests must be configured with `[workspace]`",
52                    manifest.display()
53                )
54            }
55            Self::PackageNotFound(workspace, name) => {
56                return write!(
57                    f,
58                    "package `{}` not found in workspace `{}`",
59                    name,
60                    workspace.display()
61                )
62            }
63            Self::ManifestNotInWorkspace {
64                manifest,
65                workspace_manifest,
66            } => {
67                return write!(f, "current package believes it's in a workspace when it's not:
68current:   {}
69workspace: {workspace_manifest_path}
70
71this may be fixable by adding `{package_subpath}` to the `workspace.members` array of the manifest located at: {workspace_manifest_path}
72Alternatively, to keep it out of the workspace, add an empty `[workspace]` table to the package's manifest.",
73                    // TODO: Parse workspace.exclude and add back "add the package to the `workspace.exclude` array, or"
74                    manifest.display(),
75                    package_subpath = manifest.parent().unwrap().strip_prefix(workspace_manifest.parent().unwrap()).unwrap().display(),
76                    workspace_manifest_path = workspace_manifest.display(),
77                )
78            },
79            Self::Io(path, error) => return write!(f, "{}: {}", path.display(), error),
80            Self::Toml(file, error) => return write!(f, "{}: {}", file.display(), error),
81            Self::BinNotFound(name) => return write!(f, "Can't find `{name}` bin at `src/bin/{name}.rs` or `src/bin/{name}/main.rs`. Please specify bin.path if you want to use a non-default path.", name = name),
82            Self::ExampleNotFound(name) => return write!(f, "Can't find `{name}` example at `examples/{name}.rs` or `examples/{name}/main.rs`. Please specify examples.path if you want to use a non-default path.", name = name),
83            Self::DuplicateBin(name) => return write!(f, "found duplicate binary name {name}, but all binary targets must have a unique name"),
84            Self::DuplicateExample(name) => return write!(f, "found duplicate example name {name}, but all example targets must have a unique name"),
85        })
86    }
87}
88
89impl std::error::Error for Error {}
90
91impl From<PatternError> for Error {
92    fn from(error: PatternError) -> Self {
93        Self::GlobPatternError(error.msg)
94    }
95}
96
97impl From<GlobError> for Error {
98    fn from(error: GlobError) -> Self {
99        Self::Glob(error)
100    }
101}