Skip to content

Commit

Permalink
Merge pull request #16 from saethlin/hash-the-sysroot
Browse files Browse the repository at this point in the history
Hash the sysroot contents
  • Loading branch information
RalfJung authored Feb 11, 2024
2 parents c5d3a55 + 0157d06 commit 3702f0b
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 5 deletions.
51 changes: 51 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 @@ -12,3 +12,4 @@ description = "Build a rustc sysroot with custom flags"
tempfile = "3"
rustc_version = "0.4"
anyhow = "1.0"
walkdir = "2.4"
33 changes: 28 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::process::Command;

use anyhow::{bail, Context, Result};
use tempfile::TempDir;
use walkdir::WalkDir;

/// Returns where the given rustc stores its sysroot source code.
pub fn rustc_sysroot_src(mut rustc: Command) -> Result<PathBuf> {
Expand Down Expand Up @@ -84,6 +85,29 @@ fn make_writeable(p: &Path) -> Result<()> {
Ok(())
}

/// Hash the metadata and size of every file in a directory, recursively.
pub fn hash_recursive(path: &Path, hasher: &mut DefaultHasher) -> Result<()> {
// We sort the entries to ensure a stable hash.
for entry in WalkDir::new(path)
.follow_links(true)
.sort_by_file_name()
.into_iter()
{
let entry = entry?;
// WalkDir yields the directories as well, and File::open will succeed on them. The
// reliable way to distinguish directories here is to check explicitly.
if entry.file_type().is_dir() {
continue;
}
let meta = entry.metadata()?;
// Hashing the mtime and file size should catch basically all mutations,
// and is faster than hashing the file contents.
meta.modified()?.hash(hasher);
meta.len().hash(hasher);
}
Ok(())
}

/// The build mode to use for this sysroot.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum BuildMode {
Expand Down Expand Up @@ -220,18 +244,17 @@ impl SysrootBuilder {
&self,
src_dir: &Path,
rustc_version: &rustc_version::VersionMeta,
) -> u64 {
) -> Result<u64> {
let mut hasher = DefaultHasher::new();

// For now, we just hash in the information we have in `self`.
// Ideally we'd recursively hash the entire folder but that sounds slow?
src_dir.hash(&mut hasher);
hash_recursive(src_dir, &mut hasher)?;
self.config.hash(&mut hasher);
self.mode.hash(&mut hasher);
self.rustflags.hash(&mut hasher);
rustc_version.hash(&mut hasher);

hasher.finish()
Ok(hasher.finish())
}

fn sysroot_read_hash(&self) -> Option<u64> {
Expand Down Expand Up @@ -372,7 +395,7 @@ path = "lib.rs"
}

// Check if we even need to do anything.
let cur_hash = self.sysroot_compute_hash(src_dir, &rustc_version);
let cur_hash = self.sysroot_compute_hash(src_dir, &rustc_version)?;
if self.sysroot_read_hash() == Some(cur_hash) {
// Already done!
return Ok(());
Expand Down

0 comments on commit 3702f0b

Please sign in to comment.