mod args;
mod client;
mod features;
mod printer;
mod registry;
mod util;
#[doc(inline)]
pub use client::{Client, Version};
#[doc(hidden)]
pub use client::json;
#[doc(inline)]
pub use registry::{Crate, Registry, YankState};
#[doc(inline)]
pub use args::{Args, PkgId};
#[doc(inline)]
pub use printer::*;
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub enum OfflineError {
List,
Latest,
CacheMiss,
}
impl OfflineError {
pub fn to_error(&self) -> anyhow::Error {
let err = match self {
Self::List => {
"must be able to connect to https://crates.io to list versions"
}
Self::Latest =>{
"cannot find that crate cached, you must be able to connect to https://crates.io to get the latest version"
} ,
Self::CacheMiss => {
"crate not found in local registry or cache. must be able to connect to https://crates.io to fetch it"
},
};
anyhow::anyhow!(err)
}
}
#[derive(Debug)]
pub enum Lookup {
Partial(Version),
LocalCache(features::Workspace),
Workspace(features::Workspace),
}
pub fn lookup(pkg_id: &PkgId, client: &Option<Client>, is_local: bool) -> anyhow::Result<Lookup> {
match pkg_id {
PkgId::Remote { name, semver } => {
let client = match &client {
Some(client) => client,
None => {
return Registry::from_local()?
.maybe_latest(&name)
.ok_or_else(|| OfflineError::Latest.to_error())?
.get_features()
.map(Lookup::LocalCache)
}
};
let pkg = match semver {
Some(semver) => client.get_version(name, semver),
None => client.get_latest(name),
}
.map_err(|_err| cannot_find(pkg_id))?;
Ok(Lookup::Partial(pkg))
}
PkgId::Local(path) if !is_local => Crate::from_path(path).map(Lookup::Workspace),
PkgId::Local(path) => Crate::from_local(path).map(Lookup::Workspace),
}
}
fn cannot_find(pkg_id: &PkgId) -> anyhow::Error {
anyhow::anyhow!(
"cannot find a crate matching '{}'. maybe it was yanked?",
pkg_id
)
}