Skip to content

Commit 1e57761

Browse files
committed
refactor(util-schemas): error type for PackageIdSpec
1 parent a3267bf commit 1e57761

File tree

4 files changed

+47
-29
lines changed

4 files changed

+47
-29
lines changed

crates/cargo-util-schemas/src/core/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod partial_version;
33
mod source_kind;
44

55
pub use package_id_spec::PackageIdSpec;
6+
pub use package_id_spec::PackageIdSpecError;
67
pub use partial_version::PartialVersion;
78
pub use partial_version::PartialVersionError;
89
pub use source_kind::GitReference;

crates/cargo-util-schemas/src/core/package_id_spec.rs

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use std::fmt;
22

3-
use anyhow::bail;
4-
use anyhow::Result;
53
use semver::Version;
64
use serde::{de, ser};
75
use url::Url;
@@ -11,6 +9,8 @@ use crate::core::PartialVersion;
119
use crate::core::SourceKind;
1210
use crate::manifest::PackageName;
1311

12+
type Result<T> = std::result::Result<T, PackageIdSpecError>;
13+
1414
/// Some or all of the data required to identify a package:
1515
///
1616
/// 1. the package name (a `String`, required)
@@ -83,12 +83,10 @@ impl PackageIdSpec {
8383
if abs.exists() {
8484
let maybe_url = Url::from_file_path(abs)
8585
.map_or_else(|_| "a file:// URL".to_string(), |url| url.to_string());
86-
bail!(
87-
"package ID specification `{}` looks like a file path, \
88-
maybe try {}",
89-
spec,
90-
maybe_url
91-
);
86+
return Err(PackageIdSpecError::MaybeFilePath {
87+
spec: spec.into(),
88+
maybe_url,
89+
});
9290
}
9391
}
9492
let mut parts = spec.splitn(2, [':', '@']);
@@ -119,51 +117,44 @@ impl PackageIdSpec {
119117
}
120118
"registry" => {
121119
if url.query().is_some() {
122-
bail!("cannot have a query string in a pkgid: {url}")
120+
return Err(PackageIdSpecError::UnexpectedQueryString(url));
123121
}
124122
kind = Some(SourceKind::Registry);
125123
url = strip_url_protocol(&url);
126124
}
127125
"sparse" => {
128126
if url.query().is_some() {
129-
bail!("cannot have a query string in a pkgid: {url}")
127+
return Err(PackageIdSpecError::UnexpectedQueryString(url));
130128
}
131129
kind = Some(SourceKind::SparseRegistry);
132130
// Leave `sparse` as part of URL, see `SourceId::new`
133131
// url = strip_url_protocol(&url);
134132
}
135133
"path" => {
136134
if url.query().is_some() {
137-
bail!("cannot have a query string in a pkgid: {url}")
135+
return Err(PackageIdSpecError::UnexpectedQueryString(url));
138136
}
139137
if scheme != "file" {
140-
anyhow::bail!("`path+{scheme}` is unsupported; `path+file` and `file` schemes are supported");
138+
return Err(PackageIdSpecError::UnsupportedPathPlusScheme(scheme.into()));
141139
}
142140
kind = Some(SourceKind::Path);
143141
url = strip_url_protocol(&url);
144142
}
145-
kind => anyhow::bail!("unsupported source protocol: {kind}"),
143+
kind => return Err(PackageIdSpecError::UnsupportedProtocol(kind.into())),
146144
}
147145
} else {
148146
if url.query().is_some() {
149-
bail!("cannot have a query string in a pkgid: {url}")
147+
return Err(PackageIdSpecError::UnexpectedQueryString(url));
150148
}
151149
}
152150

153151
let frag = url.fragment().map(|s| s.to_owned());
154152
url.set_fragment(None);
155153

156154
let (name, version) = {
157-
let mut path = url
158-
.path_segments()
159-
.ok_or_else(|| anyhow::format_err!("pkgid urls must have a path: {}", url))?;
160-
let path_name = path.next_back().ok_or_else(|| {
161-
anyhow::format_err!(
162-
"pkgid urls must have at least one path \
163-
component: {}",
164-
url
165-
)
166-
})?;
155+
let Some(path_name) = url.path_segments().and_then(|mut p| p.next_back()) else {
156+
return Err(PackageIdSpecError::MissingUrlPath(url));
157+
};
167158
match frag {
168159
Some(fragment) => match fragment.split_once([':', '@']) {
169160
Some((name, part)) => {
@@ -259,7 +250,7 @@ impl fmt::Display for PackageIdSpec {
259250
}
260251

261252
impl ser::Serialize for PackageIdSpec {
262-
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
253+
fn serialize<S>(&self, s: S) -> std::result::Result<S::Ok, S::Error>
263254
where
264255
S: ser::Serializer,
265256
{
@@ -268,7 +259,7 @@ impl ser::Serialize for PackageIdSpec {
268259
}
269260

270261
impl<'de> de::Deserialize<'de> for PackageIdSpec {
271-
fn deserialize<D>(d: D) -> Result<PackageIdSpec, D::Error>
262+
fn deserialize<D>(d: D) -> std::result::Result<PackageIdSpec, D::Error>
272263
where
273264
D: de::Deserializer<'de>,
274265
{
@@ -277,6 +268,32 @@ impl<'de> de::Deserialize<'de> for PackageIdSpec {
277268
}
278269
}
279270

271+
/// Error parsing a [`PackageIdSpec`].
272+
#[non_exhaustive]
273+
#[derive(Debug, thiserror::Error)]
274+
pub enum PackageIdSpecError {
275+
#[error("unsupported source protocol: {0}")]
276+
UnsupportedProtocol(String),
277+
278+
#[error("`path+{0}` is unsupported; `path+file` and `file` schemes are supported")]
279+
UnsupportedPathPlusScheme(String),
280+
281+
#[error("cannot have a query string in a pkgid: {0}")]
282+
UnexpectedQueryString(Url),
283+
284+
#[error("pkgid urls must have at least one path component: {0}")]
285+
MissingUrlPath(Url),
286+
287+
#[error("package ID specification `{spec}` looks like a file path, maybe try {maybe_url}")]
288+
MaybeFilePath { spec: String, maybe_url: String },
289+
290+
#[error(transparent)]
291+
NameValidation(#[from] crate::restricted_names::NameValidationError),
292+
293+
#[error(transparent)]
294+
PartialVersion(#[from] crate::core::PartialVersionError),
295+
}
296+
280297
#[cfg(test)]
281298
mod tests {
282299
use super::PackageIdSpec;

src/cargo/ops/cargo_compile/packages.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl Packages {
7272
let mut specs = packages
7373
.iter()
7474
.map(|p| PackageIdSpec::parse(p))
75-
.collect::<CargoResult<Vec<_>>>()?;
75+
.collect::<Result<Vec<_>, _>>()?;
7676
if !patterns.is_empty() {
7777
let matched_pkgs = ws
7878
.members()

src/cargo/ops/tree/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
186186
opts.invert
187187
.iter()
188188
.map(|p| PackageIdSpec::parse(p))
189-
.collect::<CargoResult<Vec<PackageIdSpec>>>()?
189+
.collect::<Result<Vec<PackageIdSpec>, _>>()?
190190
};
191191
let root_ids = ws_resolve.targeted_resolve.specs_to_ids(&root_specs)?;
192192
let root_indexes = graph.indexes_from_ids(&root_ids);
@@ -207,7 +207,7 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
207207
let pkgs_to_prune = opts
208208
.pkgs_to_prune
209209
.iter()
210-
.map(|p| PackageIdSpec::parse(p))
210+
.map(|p| PackageIdSpec::parse(p).map_err(Into::into))
211211
.map(|r| {
212212
// Provide an error message if pkgid is not within the resolved
213213
// dependencies graph.

0 commit comments

Comments
 (0)