Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dist: Support a bincoded manifest file for performance reasons #2627

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 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
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ no-self-update = []
# Sorted by alphabetic order
[dependencies]
anyhow = "1.0.31"
bincode = "1.3.1"
cfg-if = "1.0"
chrono = "0.4"
clap = "2"
Expand Down
5 changes: 3 additions & 2 deletions src/dist/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::str::FromStr;
use chrono::{Date, NaiveDate, TimeZone, Utc};
use lazy_static::lazy_static;
use regex::Regex;
use serde::{Deserialize, Serialize};

use crate::dist::download::DownloadCfg;
use crate::dist::manifest::Manifest as ManifestV2;
Expand Down Expand Up @@ -64,7 +65,7 @@ pub struct ToolchainDesc {
pub target: TargetTriple,
}

#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub struct TargetTriple(String);

// Linux hosts don't indicate clib in uname, however binaries only
Expand Down Expand Up @@ -417,7 +418,7 @@ impl<'a> Manifest<'a> {
}
}

#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub enum Profile {
Minimal,
Default,
Expand Down
14 changes: 8 additions & 6 deletions src/dist/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::str::FromStr;

use serde::{Deserialize, Serialize};

pub const SUPPORTED_MANIFEST_VERSIONS: [&str; 1] = ["2"];
pub const DEFAULT_MANIFEST_VERSION: &str = "2";

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Manifest {
pub manifest_version: String,
pub date: String,
Expand All @@ -33,33 +35,33 @@ pub struct Manifest {
pub profiles: HashMap<Profile, Vec<String>>,
}

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Package {
pub version: String,
pub targets: PackageTargets,
}

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum PackageTargets {
Wildcard(TargetedPackage),
Targeted(HashMap<TargetTriple, TargetedPackage>),
}

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct TargetedPackage {
pub bins: Option<PackageBins>,
pub components: Vec<Component>,
}

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct PackageBins {
pub url: String,
pub hash: String,
pub xz_url: Option<String>,
pub xz_hash: Option<String>,
}

#[derive(Clone, Debug, Eq, Ord, PartialOrd)]
#[derive(Clone, Debug, Eq, Ord, PartialOrd, Serialize, Deserialize)]
pub struct Component {
pkg: String,
pub target: Option<TargetTriple>,
Expand Down
15 changes: 15 additions & 0 deletions src/dist/manifestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::errors::*;
use crate::process;
use crate::utils::utils;

pub const DIST_MANIFEST_BINCODE: &str = "rustup-channel-manifest.bin";
pub const DIST_MANIFEST: &str = "multirust-channel-manifest.toml";
pub const CONFIG_FILE: &str = "multirust-config.toml";

Expand Down Expand Up @@ -120,7 +121,9 @@ impl Manifestation {
let temp_cfg = download_cfg.temp_cfg;
let prefix = self.installation.prefix();
let rel_installed_manifest_path = prefix.rel_manifest_file(DIST_MANIFEST);
let rel_installed_manifest_bin_path = prefix.rel_manifest_file(DIST_MANIFEST_BINCODE);
let installed_manifest_path = prefix.path().join(&rel_installed_manifest_path);
let installed_manifest_bin_path = prefix.path().join(&rel_installed_manifest_bin_path);

// Create the lists of components needed for installation
let config = self.read_config()?;
Expand Down Expand Up @@ -269,6 +272,13 @@ impl Manifestation {
let new_manifest_str = new_manifest.clone().stringify();
tx.modify_file(rel_installed_manifest_path)?;
utils::write_file("manifest", &installed_manifest_path, &new_manifest_str)?;
let new_manifest_bytes = bincode::serialize(&new_manifest)?;
tx.modify_file(rel_installed_manifest_bin_path)?;
utils::write_file_bytes(
"manifest",
&installed_manifest_bin_path,
&new_manifest_bytes,
)?;

// Write configuration.
//
Expand Down Expand Up @@ -358,6 +368,11 @@ impl Manifestation {

pub fn load_manifest(&self) -> Result<Option<Manifest>> {
let prefix = self.installation.prefix();
let manifest_bin_path = prefix.manifest_file(DIST_MANIFEST_BINCODE);
if utils::path_exists(&manifest_bin_path) {
let manifest_bytes = utils::read_file_bytes("installed manifest", &manifest_bin_path)?;
return Ok(Some(bincode::deserialize(&manifest_bytes)?));
}
let old_manifest_path = prefix.manifest_file(DIST_MANIFEST);
if utils::path_exists(&old_manifest_path) {
let manifest_str = utils::read_file("installed manifest", &old_manifest_path)?;
Expand Down
1 change: 1 addition & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ error_chain! {
Io(io::Error);
Open(opener::OpenError);
Thread(std::sync::mpsc::RecvError);
Bincode(bincode::Error);
}

errors {
Expand Down
8 changes: 6 additions & 2 deletions src/utils/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,24 @@ pub fn if_not_empty<S: PartialEq<str>>(s: S) -> Option<S> {
}
}

pub fn write_file(path: &Path, contents: &str) -> io::Result<()> {
pub fn write_file_bytes(path: &Path, contents: &[u8]) -> io::Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I note this is doing a sync_data - this is an important part of the contract of the function; if we're renaming it perhaps consider exposing that at the same time - e.g. namespacing it or adding _synced or something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this idea and will sort it out

let mut file = fs::OpenOptions::new()
.write(true)
.truncate(true)
.create(true)
.open(path)?;

io::Write::write_all(&mut file, contents.as_bytes())?;
io::Write::write_all(&mut file, contents)?;

file.sync_data()?;

Ok(())
}

pub fn write_file(path: &Path, contents: &str) -> io::Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this pays for itself vs write_file(path, contents.as_bytes())?;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, I'll sort out a refactor commit alongside this which pushes that up to the call sites.

write_file_bytes(path, contents.as_bytes())
}

pub fn filter_file<F: FnMut(&str) -> bool>(
src: &Path,
dest: &Path,
Expand Down
7 changes: 7 additions & 0 deletions src/utils/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ pub fn read_file(name: &'static str, path: &Path) -> Result<String> {
})
}

pub fn write_file_bytes(name: &'static str, path: &Path, contents: &[u8]) -> Result<()> {
raw::write_file_bytes(path, contents).chain_err(|| ErrorKind::WritingFile {
name,
path: PathBuf::from(path),
})
}

pub fn write_file(name: &'static str, path: &Path, contents: &str) -> Result<()> {
raw::write_file(path, contents).chain_err(|| ErrorKind::WritingFile {
name,
Expand Down