1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
//! Provides the various error types for this crate
#[cfg(feature = "git")]
pub use crate::index::git_remote::GitError;
#[cfg(feature = "local")]
pub use crate::index::local::LocalRegistryError;
/// The core error type for this library
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Failed to deserialize a local cache entry
#[error(transparent)]
Cache(#[from] CacheError),
/// This library assumes utf-8 paths in all cases, a path was provided that
/// was not valid utf-8
#[error("unable to use non-utf8 path {:?}", .0)]
NonUtf8Path(std::path::PathBuf),
/// A user-provided string was not a valid crate name
#[error(transparent)]
InvalidKrateName(#[from] InvalidKrateName),
/// An I/O error
#[error(transparent)]
Io(#[from] std::io::Error),
/// An I/O error occurred trying to access a specific path
#[error("I/O operation failed for path '{}': {}", .1, .0)]
IoPath(#[source] std::io::Error, crate::PathBuf),
/// A user provided URL was invalid
#[error(transparent)]
InvalidUrl(#[from] InvalidUrl),
/// Failed to de/serialize JSON
#[error(transparent)]
Json(#[from] serde_json::Error),
/// Failed to deserialize TOML
#[error(transparent)]
Toml(#[from] Box<toml_span::Error>),
/// An index entry did not contain any versions
#[error("index entry contained no versions for the crate")]
NoCrateVersions,
/// Failed to handle an HTTP response or request
#[error(transparent)]
Http(#[from] HttpError),
/// An error occurred doing a git operation
#[cfg(feature = "git")]
#[error(transparent)]
Git(#[from] GitError),
/// Failed to parse a semver version or requirement
#[error(transparent)]
Semver(#[from] semver::Error),
/// A local registry is invalid
#[cfg(feature = "local")]
#[error(transparent)]
Local(#[from] LocalRegistryError),
/// Failed to lock a file
#[error(transparent)]
Lock(#[from] crate::utils::flock::FileLockError),
}
impl From<std::path::PathBuf> for Error {
fn from(p: std::path::PathBuf) -> Self {
Self::NonUtf8Path(p)
}
}
/// Various kinds of reserved names disallowed by cargo
#[derive(Debug, Copy, Clone)]
pub enum ReservedNameKind {
/// The name is a Rust keyword
Keyword,
/// The name conflicts with a cargo artifact directory
Artifact,
/// The name has a special meaning on Windows
Windows,
/// The name conflicts with a Rust std library name
Standard,
}
impl std::fmt::Display for ReservedNameKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Keyword => f.write_str("rustlang keyword"),
Self::Artifact => f.write_str("cargo artifact"),
Self::Windows => f.write_str("windows reserved"),
Self::Standard => f.write_str("rustlang std library"),
}
}
}
/// Errors that can occur when validating a crate name
#[derive(Debug, thiserror::Error)]
pub enum InvalidKrateName {
/// The name had an invalid length
#[error("crate name had an invalid length of '{0}'")]
InvalidLength(usize),
/// The name contained an invalid character
#[error("invalid character '{invalid}` @ {index}")]
InvalidCharacter {
/// The invalid character
invalid: char,
/// The index of the character in the provided string
index: usize,
},
/// The name was one of the reserved names disallowed by cargo
#[error("the name '{reserved}' is reserved as '{kind}`")]
ReservedName {
/// The name that was reserved
reserved: &'static str,
/// The kind of the reserved name
kind: ReservedNameKind,
},
}
/// An error pertaining to a bad URL provided to the API
#[derive(Debug, thiserror::Error)]
#[error("the url '{url}' is invalid")]
pub struct InvalidUrl {
/// The invalid url
pub url: String,
/// The reason it is invalid
pub source: InvalidUrlError,
}
/// The specific reason for the why the URL is invalid
#[derive(Debug, thiserror::Error)]
pub enum InvalidUrlError {
/// Sparse HTTP registry urls must be of the form `sparse+http(s)://`
#[error("sparse indices require the use of a url that starts with `sparse+http`")]
MissingSparse,
/// The `<modifier>+<scheme>://` is not supported
#[error("the scheme modifier is unknown")]
UnknownSchemeModifier,
/// Unable to find the `<scheme>://`
#[error("the scheme is missing")]
MissingScheme,
/// Attempted to construct a git index with a sparse URL
#[error("attempted to create a git index for a sparse URL")]
SparseForGit,
}
/// Errors related to a local index cache
#[derive(Debug, thiserror::Error)]
pub enum CacheError {
/// The cache entry is malformed
#[error("the cache entry is malformed")]
InvalidCacheEntry,
/// The cache version is old
#[error("the cache entry is an old, unsupported version")]
OutdatedCacheVersion,
/// The cache version is newer than the version supported by this crate
#[error("the cache entry is an unknown version, possibly written by a newer cargo version")]
UnknownCacheVersion,
/// The index version is newer than the version supported by this crate
#[error(
"the cache entry's index version is unknown, possibly written by a newer cargo version"
)]
UnknownIndexVersion,
/// The revision in the cache entry did match the requested revision
///
/// This can occur when a git index is fetched and a newer revision is pulled
/// from the remote index, invalidating all local cache entries
#[error("the cache entry's revision does not match the current revision")]
OutdatedRevision,
/// A crate version in the cache file was malformed
#[error("a specific version in the cache entry is malformed")]
InvalidCrateVersion,
}
/// Errors related to HTTP requests or responses
#[derive(Debug, thiserror::Error)]
pub enum HttpError {
/// A [`reqwest::Error`]
#[cfg(any(feature = "sparse", feature = "local-builder"))]
#[error(transparent)]
Reqwest(#[from] reqwest::Error),
/// A status code was received that indicates user error, or possibly a
/// remote index that does not follow the protocol supported by this crate
#[error("status code '{code}': {msg}")]
StatusCode {
/// The status code
code: http::StatusCode,
/// The reason the status code raised an error
msg: &'static str,
},
/// A [`http::Error`]
#[error(transparent)]
Http(#[from] http::Error),
/// A string could not be parsed as a valid header value
#[error(transparent)]
InvalidHeaderValue(#[from] http::header::InvalidHeaderValue),
/// Unable to complete an async request for an `AsyncRemoteSparseIndex` within
/// the user allotted time
#[error("request could not be completed in the allotted timeframe")]
Timeout,
}