Skip to content

Commit

Permalink
Hash the sysroot contents
Browse files Browse the repository at this point in the history
  • Loading branch information
saethlin committed Feb 10, 2024
1 parent c5d3a55 commit 2dd67fc
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 7 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"
38 changes: 31 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@
use std::collections::hash_map::DefaultHasher;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::fs::{self, File};
use std::hash::{Hash, Hasher};
use std::io::{BufRead, BufReader};
use std::ops::Not;
use std::path::{Path, PathBuf};
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 +86,30 @@ fn make_writeable(p: &Path) -> Result<()> {
Ok(())
}

/// Hash the contents of every file in a directory, recursively.
pub fn hash_recursive(path: &Path, hasher: &mut DefaultHasher) -> Result<()> {
for entry in WalkDir::new(path).follow_links(true).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 file = File::open(entry.path())?;
let mut reader = BufReader::new(file);
while let Ok(buf) = reader.fill_buf() {
if buf.is_empty() {
// EOF is not an error, we just get an empty buffer.
break;
}
hasher.write(buf);
let len = buf.len();
reader.consume(len);
}
}
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 +246,16 @@ 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 +396,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 2dd67fc

Please sign in to comment.