mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-24 22:30:03 +00:00
Write to .crates2.json
This commit is contained in:
parent
1c2d005fd4
commit
17cf6f5dc5
7 changed files with 296 additions and 188 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -151,6 +151,7 @@ dependencies = [
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
"semver",
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"simplelog",
|
"simplelog",
|
||||||
"strum",
|
"strum",
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
|
@ -1204,9 +1205,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.81"
|
version = "1.0.82"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
|
checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
|
|
|
@ -36,6 +36,7 @@ reqwest = { version = "0.11.11", features = ["rustls-tls", "stream"], default-fe
|
||||||
scopeguard = "1.1.0"
|
scopeguard = "1.1.0"
|
||||||
semver = "1.0.10"
|
semver = "1.0.10"
|
||||||
serde = { version = "1.0.136", features = ["derive"] }
|
serde = { version = "1.0.136", features = ["derive"] }
|
||||||
|
serde_json = "1.0.82"
|
||||||
simplelog = "0.12.0"
|
simplelog = "0.12.0"
|
||||||
strum = "0.24.1"
|
strum = "0.24.1"
|
||||||
strum_macros = "0.24.2"
|
strum_macros = "0.24.2"
|
||||||
|
|
46
src/main.rs
46
src/main.rs
|
@ -1,4 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::BTreeSet,
|
||||||
ffi::OsString,
|
ffi::OsString,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process::{ExitCode, Termination},
|
process::{ExitCode, Termination},
|
||||||
|
@ -454,20 +455,13 @@ async fn install_from_package(
|
||||||
|
|
||||||
uithread.confirm().await?;
|
uithread.confirm().await?;
|
||||||
|
|
||||||
debug!("Writing .crates.toml");
|
let cvs = metafiles::CrateVersionSource {
|
||||||
if let Ok(mut ctoml) = metafiles::CratesToml::load().await {
|
name: opts.name,
|
||||||
ctoml.insert(
|
version: package.version.parse().into_diagnostic()?,
|
||||||
metafiles::CrateVersionSource {
|
source: metafiles::Source::Registry(
|
||||||
name: opts.name.into(),
|
url::Url::parse("https://github.com/rust-lang/crates.io-index").unwrap(),
|
||||||
version: package.version.parse().into_diagnostic()?,
|
),
|
||||||
source: metafiles::Source::Registry(
|
};
|
||||||
url::Url::parse("https://github.com/rust-lang/crates.io-index").unwrap(),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
bin_files.iter().map(|bin| bin.base_name.clone()),
|
|
||||||
);
|
|
||||||
ctoml.write().await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("Installing binaries...");
|
info!("Installing binaries...");
|
||||||
block_in_place(|| {
|
block_in_place(|| {
|
||||||
|
@ -490,6 +484,30 @@ async fn install_from_package(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let bins: BTreeSet<String> = bin_files.iter().map(|bin| bin.base_name.clone()).collect();
|
||||||
|
|
||||||
|
debug!("Writing .crates.toml");
|
||||||
|
if let Ok(mut c1) = metafiles::v1::CratesToml::load() {
|
||||||
|
c1.insert(cvs.clone(), bins.clone());
|
||||||
|
c1.write()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("Writing .crates2.json");
|
||||||
|
if let Ok(mut c2) = metafiles::v2::Crates2Json::load() {
|
||||||
|
c2.insert(
|
||||||
|
cvs.clone(),
|
||||||
|
metafiles::v2::CrateInfo {
|
||||||
|
version_req: Some(opts.version),
|
||||||
|
bins,
|
||||||
|
profile: "release".into(),
|
||||||
|
target: fetcher.target().to_string(),
|
||||||
|
rustc: format!("{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
c2.write()?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
176
src/metafiles.rs
176
src/metafiles.rs
|
@ -1,173 +1,5 @@
|
||||||
use std::{
|
mod cvs;
|
||||||
collections::{BTreeMap, BTreeSet},
|
pub use cvs::*;
|
||||||
fmt,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
str::FromStr,
|
|
||||||
};
|
|
||||||
|
|
||||||
use miette::Diagnostic;
|
pub mod v1;
|
||||||
use semver::Version;
|
pub mod v2;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use thiserror::Error;
|
|
||||||
use tokio::fs;
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
|
||||||
pub struct CratesTomlRaw {
|
|
||||||
#[serde(default)]
|
|
||||||
pub v1: BTreeMap<String, BTreeSet<String>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
|
||||||
pub struct CratesToml(BTreeMap<CrateVersionSource, BTreeSet<String>>);
|
|
||||||
|
|
||||||
impl CratesToml {
|
|
||||||
pub fn default_path() -> Result<PathBuf, CratesTomlParseError> {
|
|
||||||
Ok(home::cargo_home()?.join(".crates.toml"))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn load() -> Result<Self, CratesTomlParseError> {
|
|
||||||
Self::load_from_path(Self::default_path()?).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn load_from_path(path: impl AsRef<Path>) -> Result<Self, CratesTomlParseError> {
|
|
||||||
let file = fs::read_to_string(path).await?;
|
|
||||||
Self::from_str(&file)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert(&mut self, cvs: CrateVersionSource, bins: impl Iterator<Item = String>) {
|
|
||||||
self.0.insert(cvs, bins.collect());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn write(&self) -> Result<(), CratesTomlParseError> {
|
|
||||||
self.write_to_path(Self::default_path()?).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn write_to_path(&self, path: impl AsRef<Path>) -> Result<(), CratesTomlParseError> {
|
|
||||||
let raw = CratesTomlRaw {
|
|
||||||
v1: self
|
|
||||||
.0
|
|
||||||
.iter()
|
|
||||||
.map(|(cvs, bins)| (cvs.to_string(), bins.clone()))
|
|
||||||
.collect(),
|
|
||||||
};
|
|
||||||
|
|
||||||
fs::write(path, &toml::to_vec(&raw)?).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for CratesToml {
|
|
||||||
type Err = CratesTomlParseError;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let raw: CratesTomlRaw = toml::from_str(s).unwrap();
|
|
||||||
|
|
||||||
Ok(Self(
|
|
||||||
raw.v1
|
|
||||||
.into_iter()
|
|
||||||
.map(|(name, bins)| CrateVersionSource::from_str(&name).map(|cvs| (cvs, bins)))
|
|
||||||
.collect::<Result<_, _>>()?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Diagnostic, Error)]
|
|
||||||
pub enum CratesTomlParseError {
|
|
||||||
#[error(transparent)]
|
|
||||||
Io(#[from] std::io::Error),
|
|
||||||
|
|
||||||
#[error(transparent)]
|
|
||||||
TomlParse(#[from] toml::de::Error),
|
|
||||||
|
|
||||||
#[error(transparent)]
|
|
||||||
TomlWrite(#[from] toml::ser::Error),
|
|
||||||
|
|
||||||
#[error(transparent)]
|
|
||||||
CvsParse(#[from] CvsParseError),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
|
||||||
pub struct CrateVersionSource {
|
|
||||||
pub name: String,
|
|
||||||
pub version: Version,
|
|
||||||
pub source: Source,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
|
||||||
pub enum Source {
|
|
||||||
Git(Url),
|
|
||||||
Path(Url),
|
|
||||||
Registry(Url),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for CrateVersionSource {
|
|
||||||
type Err = CvsParseError;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
match s.splitn(3, ' ').collect::<Vec<_>>()[..] {
|
|
||||||
[name, version, source] => {
|
|
||||||
let version = version.parse()?;
|
|
||||||
let source = match source
|
|
||||||
.trim_matches(&['(', ')'][..])
|
|
||||||
.splitn(2, '+')
|
|
||||||
.collect::<Vec<_>>()[..]
|
|
||||||
{
|
|
||||||
["git", url] => Source::Git(Url::parse(url)?),
|
|
||||||
["path", url] => Source::Path(Url::parse(url)?),
|
|
||||||
["registry", url] => Source::Registry(Url::parse(url)?),
|
|
||||||
[kind, arg] => {
|
|
||||||
return Err(CvsParseError::UnknownSourceType {
|
|
||||||
kind: kind.to_string(),
|
|
||||||
arg: arg.to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => return Err(CvsParseError::BadSource),
|
|
||||||
};
|
|
||||||
Ok(Self {
|
|
||||||
name: name.to_string(),
|
|
||||||
version,
|
|
||||||
source,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => Err(CvsParseError::BadFormat),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Diagnostic, Error)]
|
|
||||||
pub enum CvsParseError {
|
|
||||||
#[error(transparent)]
|
|
||||||
UrlParse(#[from] url::ParseError),
|
|
||||||
|
|
||||||
#[error(transparent)]
|
|
||||||
VersionParse(#[from] semver::Error),
|
|
||||||
|
|
||||||
#[error("unknown source type {kind}+{arg}")]
|
|
||||||
UnknownSourceType { kind: String, arg: String },
|
|
||||||
|
|
||||||
#[error("bad source format")]
|
|
||||||
BadSource,
|
|
||||||
|
|
||||||
#[error("bad CVS format")]
|
|
||||||
BadFormat,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for CrateVersionSource {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
let Self {
|
|
||||||
name,
|
|
||||||
version,
|
|
||||||
source,
|
|
||||||
} = &self;
|
|
||||||
write!(f, "{name} {version} ({source})")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Source {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Source::Git(url) => write!(f, "git+{url}"),
|
|
||||||
Source::Path(url) => write!(f, "path+{url}"),
|
|
||||||
Source::Registry(url) => write!(f, "registry+{url}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
111
src/metafiles/cvs.rs
Normal file
111
src/metafiles/cvs.rs
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
use std::{fmt, str::FromStr};
|
||||||
|
|
||||||
|
use miette::Diagnostic;
|
||||||
|
use semver::Version;
|
||||||
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
use thiserror::Error;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
|
pub struct CrateVersionSource {
|
||||||
|
pub name: String,
|
||||||
|
pub version: Version,
|
||||||
|
pub source: Source,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
|
pub enum Source {
|
||||||
|
Git(Url),
|
||||||
|
Path(Url),
|
||||||
|
Registry(Url),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for CrateVersionSource {
|
||||||
|
type Err = CvsParseError;
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s.splitn(3, ' ').collect::<Vec<_>>()[..] {
|
||||||
|
[name, version, source] => {
|
||||||
|
let version = version.parse()?;
|
||||||
|
let source = match source
|
||||||
|
.trim_matches(&['(', ')'][..])
|
||||||
|
.splitn(2, '+')
|
||||||
|
.collect::<Vec<_>>()[..]
|
||||||
|
{
|
||||||
|
["git", url] => Source::Git(Url::parse(url)?),
|
||||||
|
["path", url] => Source::Path(Url::parse(url)?),
|
||||||
|
["registry", url] => Source::Registry(Url::parse(url)?),
|
||||||
|
[kind, arg] => {
|
||||||
|
return Err(CvsParseError::UnknownSourceType {
|
||||||
|
kind: kind.to_string(),
|
||||||
|
arg: arg.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => return Err(CvsParseError::BadSource),
|
||||||
|
};
|
||||||
|
Ok(Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
version,
|
||||||
|
source,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => Err(CvsParseError::BadFormat),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
pub enum CvsParseError {
|
||||||
|
#[error(transparent)]
|
||||||
|
UrlParse(#[from] url::ParseError),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
VersionParse(#[from] semver::Error),
|
||||||
|
|
||||||
|
#[error("unknown source type {kind}+{arg}")]
|
||||||
|
UnknownSourceType { kind: String, arg: String },
|
||||||
|
|
||||||
|
#[error("bad source format")]
|
||||||
|
BadSource,
|
||||||
|
|
||||||
|
#[error("bad CVS format")]
|
||||||
|
BadFormat,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for CrateVersionSource {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let Self {
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
source,
|
||||||
|
} = &self;
|
||||||
|
write!(f, "{name} {version} ({source})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Source {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Source::Git(url) => write!(f, "git+{url}"),
|
||||||
|
Source::Path(url) => write!(f, "path+{url}"),
|
||||||
|
Source::Registry(url) => write!(f, "registry+{url}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for CrateVersionSource {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&self.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for CrateVersionSource {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
Self::from_str(&String::deserialize(deserializer)?).map_err(serde::de::Error::custom)
|
||||||
|
}
|
||||||
|
}
|
67
src/metafiles/v1.rs
Normal file
67
src/metafiles/v1.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
use std::{
|
||||||
|
collections::{BTreeMap, BTreeSet},
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
|
use miette::Diagnostic;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use super::CrateVersionSource;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||||
|
pub struct CratesToml {
|
||||||
|
v1: BTreeMap<CrateVersionSource, BTreeSet<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CratesToml {
|
||||||
|
pub fn default_path() -> Result<PathBuf, CratesTomlParseError> {
|
||||||
|
Ok(home::cargo_home()?.join(".crates.toml"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load() -> Result<Self, CratesTomlParseError> {
|
||||||
|
Self::load_from_path(Self::default_path()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_from_path(path: impl AsRef<Path>) -> Result<Self, CratesTomlParseError> {
|
||||||
|
let file = fs::read_to_string(path)?;
|
||||||
|
Self::from_str(&file)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, cvs: CrateVersionSource, bins: BTreeSet<String>) {
|
||||||
|
self.v1.insert(cvs, bins);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self) -> Result<(), CratesTomlParseError> {
|
||||||
|
self.write_to_path(Self::default_path()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_to_path(&self, path: impl AsRef<Path>) -> Result<(), CratesTomlParseError> {
|
||||||
|
fs::write(path, &toml::to_vec(&self)?)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for CratesToml {
|
||||||
|
type Err = CratesTomlParseError;
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(toml::from_str(s)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
pub enum CratesTomlParseError {
|
||||||
|
#[error(transparent)]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
TomlParse(#[from] toml::de::Error),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
TomlWrite(#[from] toml::ser::Error),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
CvsParse(#[from] super::CvsParseError),
|
||||||
|
}
|
78
src/metafiles/v2.rs
Normal file
78
src/metafiles/v2.rs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
use std::{
|
||||||
|
collections::{BTreeMap, BTreeSet},
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use miette::Diagnostic;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use super::CrateVersionSource;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||||
|
pub struct Crates2Json {
|
||||||
|
pub installs: BTreeMap<CrateVersionSource, CrateInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||||
|
pub struct CrateInfo {
|
||||||
|
#[serde(default)]
|
||||||
|
pub version_req: Option<String>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub bins: BTreeSet<String>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub features: BTreeSet<String>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub all_features: bool,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub no_default_features: bool,
|
||||||
|
|
||||||
|
pub profile: String,
|
||||||
|
pub target: String,
|
||||||
|
pub rustc: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Crates2Json {
|
||||||
|
pub fn default_path() -> Result<PathBuf, Crates2JsonParseError> {
|
||||||
|
Ok(home::cargo_home()?.join(".crates2.json"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load() -> Result<Self, Crates2JsonParseError> {
|
||||||
|
Self::load_from_path(Self::default_path()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_from_path(path: impl AsRef<Path>) -> Result<Self, Crates2JsonParseError> {
|
||||||
|
let file = fs::read_to_string(path)?;
|
||||||
|
Ok(serde_json::from_str(&file)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, cvs: CrateVersionSource, info: CrateInfo) {
|
||||||
|
self.installs.insert(cvs, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self) -> Result<(), Crates2JsonParseError> {
|
||||||
|
self.write_to_path(Self::default_path()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_to_path(&self, path: impl AsRef<Path>) -> Result<(), Crates2JsonParseError> {
|
||||||
|
fs::write(path, &serde_json::to_vec(&self)?)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
pub enum Crates2JsonParseError {
|
||||||
|
#[error(transparent)]
|
||||||
|
Io(#[from] std::io::Error),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
Json(#[from] serde_json::Error),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
CvsParse(#[from] super::CvsParseError),
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue