Skip to content

Commit

Permalink
Refactor: Extract new crate binstalk-types plus other misc refactor a…
Browse files Browse the repository at this point in the history
…nd optimization (rust-lang#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>
  • Loading branch information
NobodyXu committed Nov 17, 2022
1 parent 58326a6 commit d9cc3ce
Show file tree
Hide file tree
Showing 24 changed files with 372 additions and 76 deletions.
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Expand Up @@ -20,6 +20,10 @@ updates:
directory: "/crates/binstalk-manifests"
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "/crates/binstalk-types"
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directory: "/crates/binstalk"
schedule:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release-pr.yml
Expand Up @@ -10,6 +10,7 @@ on:
- bin
- binstalk
- binstalk-manifests
- binstalk-types
- binstalk-downloader
- detect-targets
- detect-wasi
Expand Down
22 changes: 17 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -3,6 +3,7 @@ members = [
"crates/bin",
"crates/binstalk",
"crates/binstalk-manifests",
"crates/binstalk-types",
"crates/binstalk-downloader",
"crates/detect-wasi",
"crates/fs-lock",
Expand Down
1 change: 1 addition & 0 deletions crates/bin/Cargo.toml
Expand Up @@ -23,6 +23,7 @@ pkg-fmt = "zip"

[dependencies]
binstalk = { path = "../binstalk", version = "0.4.1" }
binstalk-manifests = { path = "../binstalk-manifests", version = "0.1.0" }
clap = { version = "4.0.25", features = ["derive"] }
crates_io_api = { version = "0.8.1", default-features = false }
dirs = "4.0.0"
Expand Down
6 changes: 3 additions & 3 deletions crates/bin/src/entry.rs
Expand Up @@ -5,14 +5,14 @@ use binstalk::{
fetchers::{Fetcher, GhCrateMeta, QuickInstall},
get_desired_targets,
helpers::{jobserver_client::LazyJobserverClient, remote::Client, tasks::AutoAbortJoinHandle},
manifests::{
binstall_crates_v1::Records, cargo_crates_v1::CratesToml, cargo_toml_binstall::PkgOverride,
},
ops::{
self,
resolve::{CrateName, Resolution, VersionReqExt},
},
};
use binstalk_manifests::{
binstall_crates_v1::Records, cargo_crates_v1::CratesToml, cargo_toml_binstall::PkgOverride,
};
use log::LevelFilter;
use miette::{miette, Result, WrapErr};
use tokio::task::block_in_place;
Expand Down
2 changes: 1 addition & 1 deletion crates/binstalk-downloader/Cargo.toml
Expand Up @@ -10,7 +10,7 @@ edition = "2021"
license = "GPL-3.0"

[dependencies]
binstalk-manifests = { version = "0.1.0", path = "../binstalk-manifests" }
binstalk-types = { version = "0.1.0", path = "../binstalk-types" }
bytes = "1.2.1"
bzip2 = "0.4.3"
digest = "0.10.5"
Expand Down
4 changes: 2 additions & 2 deletions crates/binstalk-downloader/src/download.rs
@@ -1,11 +1,11 @@
use std::{fmt::Debug, future::Future, io, marker::PhantomData, path::Path, pin::Pin};

use binstalk_manifests::cargo_toml_binstall::{PkgFmtDecomposed, TarBasedFmt};
use binstalk_types::cargo_toml_binstall::{PkgFmtDecomposed, TarBasedFmt};
use digest::{Digest, FixedOutput, HashMarker, Output, OutputSizeUser, Update};
use thiserror::Error as ThisError;
use tracing::{debug, instrument};

pub use binstalk_manifests::cargo_toml_binstall::PkgFmt;
pub use binstalk_types::cargo_toml_binstall::PkgFmt;
pub use tar::Entries;
pub use zip::result::ZipError;

Expand Down
4 changes: 1 addition & 3 deletions crates/binstalk-manifests/Cargo.toml
Expand Up @@ -10,17 +10,15 @@ edition = "2021"
license = "Apache-2.0 OR MIT"

[dependencies]
binstalk-types = { version = "0.1.0", path = "../binstalk-types" }
compact_str = { version = "0.6.0", features = ["serde"] }
fs-lock = { version = "0.1.0", path = "../fs-lock" }
home = "0.5.4"
miette = "5.4.1"
once_cell = "1.16.0"
semver = { version = "1.0.14", features = ["serde"] }
serde = { version = "1.0.147", features = ["derive"] }
serde-tuple-vec-map = "1.0.1"
serde_json = "1.0.87"
strum = "0.24.1"
strum_macros = "0.24.3"
thiserror = "1.0.37"
toml_edit = { version = "0.15.0", features = ["easy"] }
url = { version = "2.3.1", features = ["serde"] }
Expand Down
115 changes: 88 additions & 27 deletions crates/binstalk-manifests/src/binstall_crates_v1.rs
Expand Up @@ -7,24 +7,26 @@
//! NLJSON to the file will be understood fine.

use std::{
borrow::Borrow,
cmp,
collections::{btree_set, BTreeSet},
fs,
io::{self, Seek, Write},
iter::{IntoIterator, Iterator},
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),
Expand All @@ -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);
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -134,19 +198,20 @@ 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 {
self.data.remove(value.as_ref())
}

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 {
Expand All @@ -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()
Expand Down Expand Up @@ -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(),
Expand All @@ -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(),
Expand All @@ -220,7 +283,6 @@ mod test {
source: CrateSource::cratesio_registry(),
target: target.clone(),
bins: vec!["1".into()],
other: Default::default(),
},
];

Expand All @@ -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
Expand All @@ -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);
Expand Down

0 comments on commit d9cc3ce

Please sign in to comment.