Refactor: Extract new crate binstalk-types plus other misc refactor and optimization (#535)

* Refactor: Extract new crate binstalk-types
* Optimize: Rm field `CrateInfo::other`
   which also removes dep serde-tuple-vec-map and serde-json from
   binstalk-types.
   
   This also makes `CrateInfo` easier to use, more generic and can be used
   over any `Serializer`, not just `serde_json::Value`.
* Mark all errors in `binstalk-manifests` as non_exhaustive
* Reduce size of `CvsParseError` by using `Box<str>`
   instead of `String` for variant `UnknownSourceType`.
* Reduce size of `CratesTomlParseError` to 16 bytes on 64bit platform
   by boxing variants `TomlWrite` and `CvsParse` as these two fields are
   significantly larger than other variants.
* Unify import style in mod `binstall_crates_v1`
* Replace dep binstalk-manifests with binstalk-types in binstalk-downloader
   to reduce its transitive dependencies and enables binstalk-downloader to
   be built in parallel to binstak-manifests.
* Replace dep binstalk-manifests with binstalk-types in binstalk
   to reduce transitive dependencies and enables binstalk to be built in
   parallel to binstalk-manifests.
   
   This is benefitial because binstalk-manifests pulls in toml_edit, which
   could takes up to 15s to be built on M1 (7-9s for codegen).
* Add dep binstalk-manifests to crates/bin
* Update dependabot and GHA release-pr

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Jiahao XU 2022-11-17 11:46:27 +11:00 committed by GitHub
parent 58326a6085
commit d9cc3ce219
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 372 additions and 76 deletions

View file

@ -7,6 +7,8 @@
//! NLJSON to the file will be understood fine.
use std::{
borrow::Borrow,
cmp,
collections::{btree_set, BTreeSet},
fs,
io::{self, Seek, Write},
@ -14,17 +16,17 @@ use std::{
path::{Path, PathBuf},
};
use compact_str::CompactString;
use fs_lock::FileLock;
use home::cargo_home;
use miette::Diagnostic;
use serde::Serialize;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::helpers::create_if_not_exist;
use super::crate_info::CrateInfo;
use crate::{crate_info::CrateInfo, helpers::create_if_not_exist};
#[derive(Debug, Diagnostic, Error)]
#[non_exhaustive]
pub enum Error {
#[error(transparent)]
Io(#[from] io::Error),
@ -33,28 +35,27 @@ pub enum Error {
SerdeJsonParse(#[from] serde_json::Error),
}
pub fn append_to_path<Iter>(path: impl AsRef<Path>, iter: Iter) -> Result<(), Error>
pub fn append_to_path<Iter, T>(path: impl AsRef<Path>, iter: Iter) -> Result<(), Error>
where
Iter: IntoIterator<Item = CrateInfo>,
Iter: IntoIterator<Item = T>,
Data: From<T>,
{
let mut file = FileLock::new_exclusive(create_if_not_exist(path.as_ref())?)?;
// Move the cursor to EOF
file.seek(io::SeekFrom::End(0))?;
write_to(&mut file, &mut iter.into_iter())
write_to(&mut file, &mut iter.into_iter().map(Data::from))
}
pub fn append<Iter>(iter: Iter) -> Result<(), Error>
pub fn append<Iter, T>(iter: Iter) -> Result<(), Error>
where
Iter: IntoIterator<Item = CrateInfo>,
Iter: IntoIterator<Item = T>,
Data: From<T>,
{
append_to_path(default_path()?, iter)
}
pub fn write_to(
file: &mut FileLock,
iter: &mut dyn Iterator<Item = CrateInfo>,
) -> Result<(), Error> {
pub fn write_to(file: &mut FileLock, iter: &mut dyn Iterator<Item = Data>) -> Result<(), Error> {
let writer = io::BufWriter::with_capacity(512, file);
let mut ser = serde_json::Serializer::new(writer);
@ -76,11 +77,74 @@ pub fn default_path() -> Result<PathBuf, Error> {
Ok(dir.join("crates-v1.json"))
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Data {
#[serde(flatten)]
pub crate_info: CrateInfo,
/// Forwards compatibility. Unknown keys from future versions
/// will be stored here and retained when the file is saved.
///
/// We use an `Vec` here since it is never accessed in Rust.
#[serde(flatten, with = "tuple_vec_map")]
pub other: Vec<(CompactString, serde_json::Value)>,
}
impl From<CrateInfo> for Data {
fn from(crate_info: CrateInfo) -> Self {
Self {
crate_info,
other: Vec::new(),
}
}
}
impl From<Data> for CrateInfo {
fn from(data: Data) -> Self {
data.crate_info
}
}
impl Borrow<str> for Data {
fn borrow(&self) -> &str {
&self.crate_info.name
}
}
impl PartialEq for Data {
fn eq(&self, other: &Self) -> bool {
self.crate_info.name == other.crate_info.name
}
}
impl PartialEq<CrateInfo> for Data {
fn eq(&self, other: &CrateInfo) -> bool {
self.crate_info.name == other.name
}
}
impl PartialEq<Data> for CrateInfo {
fn eq(&self, other: &Data) -> bool {
self.name == other.crate_info.name
}
}
impl Eq for Data {}
impl PartialOrd for Data {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Data {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.crate_info.name.cmp(&other.crate_info.name)
}
}
#[derive(Debug)]
pub struct Records {
file: FileLock,
/// Use BTreeSet to dedup the metadata
data: BTreeSet<CrateInfo>,
data: BTreeSet<Data>,
}
impl Records {
@ -122,7 +186,7 @@ impl Records {
}
pub fn get(&self, value: impl AsRef<str>) -> Option<&CrateInfo> {
self.data.get(value.as_ref())
self.data.get(value.as_ref()).map(|data| &data.crate_info)
}
pub fn contains(&self, value: impl AsRef<str>) -> bool {
@ -134,11 +198,12 @@ impl Records {
/// If the set did have an equal element present, false is returned,
/// and the entry is not updated.
pub fn insert(&mut self, value: CrateInfo) -> bool {
self.data.insert(value)
self.data.insert(Data::from(value))
}
/// Return the previous `CrateInfo` for the package if there is any.
pub fn replace(&mut self, value: CrateInfo) -> Option<CrateInfo> {
self.data.replace(value)
self.data.replace(Data::from(value)).map(CrateInfo::from)
}
pub fn remove(&mut self, value: impl AsRef<str>) -> bool {
@ -146,7 +211,7 @@ impl Records {
}
pub fn take(&mut self, value: impl AsRef<str>) -> Option<CrateInfo> {
self.data.take(value.as_ref())
self.data.take(value.as_ref()).map(CrateInfo::from)
}
pub fn len(&self) -> usize {
@ -159,9 +224,9 @@ impl Records {
}
impl<'a> IntoIterator for &'a Records {
type Item = &'a CrateInfo;
type Item = &'a Data;
type IntoIter = btree_set::Iter<'a, CrateInfo>;
type IntoIter = btree_set::Iter<'a, Data>;
fn into_iter(self) -> Self::IntoIter {
self.data.iter()
@ -202,7 +267,6 @@ mod test {
source: CrateSource::cratesio_registry(),
target: target.clone(),
bins: vec!["1".into(), "2".into()],
other: Default::default(),
},
CrateInfo {
name: "b".into(),
@ -211,7 +275,6 @@ mod test {
source: CrateSource::cratesio_registry(),
target: target.clone(),
bins: vec!["1".into(), "2".into()],
other: Default::default(),
},
CrateInfo {
name: "a".into(),
@ -220,7 +283,6 @@ mod test {
source: CrateSource::cratesio_registry(),
target: target.clone(),
bins: vec!["1".into()],
other: Default::default(),
},
];
@ -234,11 +296,11 @@ mod test {
let mut records = Records::load_from_path(path).unwrap();
assert_records_eq!(&records, &metadata_set);
records.remove("b");
assert_eq!(records.len(), metadata_set.len() - 1);
assert!(records.remove("b"));
metadata_set.remove("b");
assert_eq!(records.len(), metadata_set.len());
records.overwrite().unwrap();
metadata_set.remove("b");
let records = Records::load_from_path(path).unwrap();
assert_records_eq!(&records, &metadata_set);
// Drop the exclusive file lock
@ -251,7 +313,6 @@ mod test {
source: CrateSource::cratesio_registry(),
target,
bins: vec!["1".into(), "2".into()],
other: Default::default(),
};
append_to_path(path, [new_metadata.clone()]).unwrap();
metadata_set.insert(new_metadata);