mirror of
https://github.com/cargo-bins/cargo-binstall.git
synced 2025-04-21 13:08:42 +00:00

Fixed #588 * Add new dep fs-lock v0.1.0 to crates/bin * Refactor: Impl new type `Manifests` in crates/bin for managing manifests. * Fix #588 race cond updating `.crates.toml` Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
85 lines
2.6 KiB
Rust
85 lines
2.6 KiB
Rust
use std::{collections::BTreeMap, fs, io::Seek, path::Path};
|
|
|
|
use binstalk::errors::BinstallError;
|
|
use binstalk_manifests::{
|
|
binstall_crates_v1::Records as BinstallCratesV1Records, cargo_crates_v1::CratesToml,
|
|
crate_info::CrateInfo, CompactString, Version,
|
|
};
|
|
use fs_lock::FileLock;
|
|
use miette::{Error, Result};
|
|
use tracing::debug;
|
|
|
|
pub struct Manifests {
|
|
binstall: BinstallCratesV1Records,
|
|
cargo_crates_v1: FileLock,
|
|
}
|
|
|
|
impl Manifests {
|
|
pub fn open_exclusive(cargo_roots: &Path) -> Result<Self> {
|
|
// Read cargo_binstall_metadata
|
|
let metadata_path = cargo_roots.join("binstall/crates-v1.json");
|
|
fs::create_dir_all(metadata_path.parent().unwrap()).map_err(BinstallError::Io)?;
|
|
|
|
debug!(
|
|
"Reading binstall metadata from {} and obtaining exclusive lock",
|
|
metadata_path.display()
|
|
);
|
|
|
|
let binstall = BinstallCratesV1Records::load_from_path(&metadata_path)?;
|
|
|
|
// Read cargo_install_v1_metadata
|
|
let manifest_path = cargo_roots.join(".crates.toml");
|
|
|
|
debug!(
|
|
"Obtaining exclusive lock of cargo install v1 metadata in path {}",
|
|
manifest_path.display()
|
|
);
|
|
|
|
let cargo_crates_v1 = fs::File::options()
|
|
.read(true)
|
|
.write(true)
|
|
.create(true)
|
|
.open(manifest_path)
|
|
.and_then(FileLock::new_exclusive)
|
|
.map_err(BinstallError::Io)?;
|
|
|
|
Ok(Self {
|
|
binstall,
|
|
cargo_crates_v1,
|
|
})
|
|
}
|
|
|
|
fn rewind_cargo_crates_v1(&mut self) -> Result<()> {
|
|
self.cargo_crates_v1
|
|
.rewind()
|
|
.map_err(BinstallError::Io)
|
|
.map_err(Error::from)
|
|
}
|
|
|
|
/// `cargo-uninstall` can be called to uninstall crates,
|
|
/// but it only updates .crates.toml.
|
|
///
|
|
/// So here we will honour .crates.toml only.
|
|
pub fn load_installed_crates(&mut self) -> Result<BTreeMap<CompactString, Version>> {
|
|
self.rewind_cargo_crates_v1()?;
|
|
|
|
CratesToml::load_from_reader(&mut self.cargo_crates_v1)
|
|
.and_then(CratesToml::collect_into_crates_versions)
|
|
.map_err(Error::from)
|
|
}
|
|
|
|
pub fn update(mut self, metadata_vec: Vec<CrateInfo>) -> Result<()> {
|
|
self.rewind_cargo_crates_v1()?;
|
|
|
|
debug!("Writing .crates.toml");
|
|
CratesToml::append_to_file(&mut self.cargo_crates_v1, &metadata_vec)?;
|
|
|
|
debug!("Writing binstall/crates-v1.json");
|
|
for metadata in metadata_vec {
|
|
self.binstall.replace(metadata);
|
|
}
|
|
self.binstall.overwrite()?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|