diff --git a/src/binstall/install.rs b/src/binstall/install.rs index c1b78fc3..875344af 100644 --- a/src/binstall/install.rs +++ b/src/binstall/install.rs @@ -108,29 +108,21 @@ async fn install_from_package( let bins: BTreeSet<String> = bin_files.into_iter().map(|bin| bin.base_name).collect(); - { - debug!("Writing .crates.toml"); - let mut c1 = metafiles::v1::CratesToml::load().unwrap_or_default(); - c1.insert(cvs.clone(), bins.clone()); - c1.write()?; - } + debug!("Writing .crates.toml"); + metafiles::v1::CratesToml::append(&cvs, bins.clone())?; - { - debug!("Writing .crates2.json"); - let mut c2 = metafiles::v2::Crates2Json::load().unwrap_or_default(); - c2.insert( - cvs, - metafiles::v2::CrateInfo { - version_req: Some(version), - bins, - profile: "release".into(), - target: fetcher.target().to_string(), - rustc: format!("{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")), - ..Default::default() - }, - ); - c2.write()?; - } + debug!("Writing .crates2.json"); + metafiles::v2::Crates2Json::append( + &cvs, + metafiles::v2::CrateInfo { + version_req: Some(version), + bins, + profile: "release".into(), + target: fetcher.target().to_string(), + rustc: format!("{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")), + ..Default::default() + }, + )?; Ok(()) }) diff --git a/src/metafiles/cvs.rs b/src/metafiles/cvs.rs index 2b8f2214..b56ab5fc 100644 --- a/src/metafiles/cvs.rs +++ b/src/metafiles/cvs.rs @@ -1,4 +1,4 @@ -use std::{fmt, str::FromStr}; +use std::{borrow::Cow, fmt, str::FromStr}; use miette::Diagnostic; use once_cell::sync::Lazy; @@ -116,6 +116,7 @@ impl<'de> Deserialize<'de> for CrateVersionSource { where D: Deserializer<'de>, { - Self::from_str(&String::deserialize(deserializer)?).map_err(serde::de::Error::custom) + let s = Cow::<'_, str>::deserialize(deserializer)?; + Self::from_str(&s).map_err(serde::de::Error::custom) } } diff --git a/src/metafiles/v1.rs b/src/metafiles/v1.rs index 19f0ab8f..3b98568d 100644 --- a/src/metafiles/v1.rs +++ b/src/metafiles/v1.rs @@ -1,6 +1,6 @@ use std::{ collections::{BTreeMap, BTreeSet}, - fs, + fs, io, path::{Path, PathBuf}, str::FromStr, }; @@ -14,7 +14,7 @@ use crate::cargo_home; #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct CratesToml { - v1: BTreeMap<CrateVersionSource, BTreeSet<String>>, + v1: BTreeMap<String, BTreeSet<String>>, } impl CratesToml { @@ -31,8 +31,8 @@ impl CratesToml { Self::from_str(&file) } - pub fn insert(&mut self, cvs: CrateVersionSource, bins: BTreeSet<String>) { - self.v1.insert(cvs, bins); + pub fn insert(&mut self, cvs: &CrateVersionSource, bins: BTreeSet<String>) { + self.v1.insert(cvs.to_string(), bins); } pub fn write(&self) -> Result<(), CratesTomlParseError> { @@ -43,6 +43,31 @@ impl CratesToml { fs::write(path, &toml::to_vec(&self)?)?; Ok(()) } + + pub fn append_to_path( + path: impl AsRef<Path>, + cvs: &CrateVersionSource, + bins: BTreeSet<String>, + ) -> Result<(), CratesTomlParseError> { + let mut c1 = match Self::load_from_path(path.as_ref()) { + Ok(c1) => c1, + Err(CratesTomlParseError::Io(io_err)) if io_err.kind() == io::ErrorKind::NotFound => { + Self::default() + } + Err(err) => return Err(err), + }; + c1.insert(cvs, bins); + c1.write_to_path(path.as_ref())?; + + Ok(()) + } + + pub fn append( + cvs: &CrateVersionSource, + bins: BTreeSet<String>, + ) -> Result<(), CratesTomlParseError> { + Self::append_to_path(Self::default_path()?, cvs, bins) + } } impl FromStr for CratesToml { @@ -55,7 +80,7 @@ impl FromStr for CratesToml { #[derive(Debug, Diagnostic, Error)] pub enum CratesTomlParseError { #[error(transparent)] - Io(#[from] std::io::Error), + Io(#[from] io::Error), #[error(transparent)] TomlParse(#[from] toml::de::Error), diff --git a/src/metafiles/v2.rs b/src/metafiles/v2.rs index 4724b1e8..f9ea6a68 100644 --- a/src/metafiles/v2.rs +++ b/src/metafiles/v2.rs @@ -1,6 +1,6 @@ use std::{ collections::{BTreeMap, BTreeSet}, - fs, + fs, io, path::{Path, PathBuf}, }; @@ -13,7 +13,7 @@ use crate::cargo_home; #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Crates2Json { - pub installs: BTreeMap<CrateVersionSource, CrateInfo>, + pub installs: BTreeMap<String, CrateInfo>, } #[derive(Clone, Debug, Default, Deserialize, Serialize)] @@ -48,12 +48,12 @@ impl Crates2Json { } 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)?) + let file = fs::File::open(path.as_ref())?; + Ok(serde_json::from_reader(file)?) } - pub fn insert(&mut self, cvs: CrateVersionSource, info: CrateInfo) { - self.installs.insert(cvs, info); + pub fn insert(&mut self, cvs: &CrateVersionSource, info: CrateInfo) { + self.installs.insert(cvs.to_string(), info); } pub fn write(&self) -> Result<(), Crates2JsonParseError> { @@ -61,15 +61,38 @@ impl Crates2Json { } pub fn write_to_path(&self, path: impl AsRef<Path>) -> Result<(), Crates2JsonParseError> { - fs::write(path, &serde_json::to_vec(&self)?)?; + let file = fs::File::create(path.as_ref())?; + serde_json::to_writer(file, &self)?; Ok(()) } + + pub fn append_to_path( + path: impl AsRef<Path>, + cvs: &CrateVersionSource, + info: CrateInfo, + ) -> Result<(), Crates2JsonParseError> { + let mut c2 = match Self::load_from_path(path.as_ref()) { + Ok(c2) => c2, + Err(Crates2JsonParseError::Io(io_err)) if io_err.kind() == io::ErrorKind::NotFound => { + Self::default() + } + Err(err) => return Err(err), + }; + c2.insert(cvs, info); + c2.write_to_path(path.as_ref())?; + + Ok(()) + } + + pub fn append(cvs: &CrateVersionSource, info: CrateInfo) -> Result<(), Crates2JsonParseError> { + Self::append_to_path(Self::default_path()?, cvs, info) + } } #[derive(Debug, Diagnostic, Error)] pub enum Crates2JsonParseError { #[error(transparent)] - Io(#[from] std::io::Error), + Io(#[from] io::Error), #[error(transparent)] Json(#[from] serde_json::Error),