Skip to content

Commit

Permalink
refactor: read JSON fingerprint reading only when needed
Browse files Browse the repository at this point in the history
  • Loading branch information
weihanglo committed Jan 28, 2024
1 parent 84584e6 commit fc2352b
Showing 1 changed file with 46 additions and 34 deletions.
80 changes: 46 additions & 34 deletions src/cargo/core/compiler/fingerprint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ use serde::{Deserialize, Serialize};
use tracing::{debug, info};

use crate::core::compiler::unit_graph::UnitDep;
use crate::core::Verbosity;
use crate::core::Package;
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
Expand Down Expand Up @@ -415,7 +416,9 @@ pub fn prepare_target(cx: &mut Context<'_, '_>, unit: &Unit, force: bool) -> Car
// information about failed comparisons to aid in debugging.
let fingerprint = calculate(cx, unit)?;
let mtime_on_use = cx.bcx.config.cli_unstable().mtime_on_use;
let dirty_reason = compare_old_fingerprint(unit, &loc, &*fingerprint, mtime_on_use, force);
let verbosity = cx.bcx.config.shell().verbosity();
let dirty_reason =
compare_old_fingerprint(unit, &loc, &*fingerprint, mtime_on_use, force, verbosity);

let Some(dirty_reason) = dirty_reason else {
return Ok(Job::new_fresh());
Expand Down Expand Up @@ -1741,35 +1744,67 @@ fn compare_old_fingerprint(
new_fingerprint: &Fingerprint,
mtime_on_use: bool,
forced: bool,
verbosity: Verbosity,
) -> Option<DirtyReason> {
let compare = _compare_old_fingerprint(old_hash_path, new_fingerprint, mtime_on_use);
log_compare(unit, &compare);
if mtime_on_use {
// update the mtime so other cleaners know we used it
let t = FileTime::from_system_time(SystemTime::now());
debug!("mtime-on-use forcing {:?} to {}", old_hash_path, t);
paths::set_file_time_no_err(old_hash_path, t);
}

let tracing_enabled = tracing::enabled!(tracing::Level::INFO);
let verbose = !matches!(verbosity, Verbosity::Quiet | Verbosity::Normal);

let compare =
_compare_old_fingerprint(old_hash_path, new_fingerprint, tracing_enabled || verbose);

if tracing_enabled {
// Logs the result of fingerprint comparison.
// TODO: Obsolete and mostly superseded by [`DirtyReason`]. Could be removed.
match compare.as_ref() {
Ok(None) => {}
Ok(Some(reason)) => {
info!(
"fingerprint dirty for {}/{:?}/{:?}",
unit.pkg, unit.mode, unit.target,
);
info!(" dirty: {reason:?}");
}
Err(e) => {
info!(
"fingerprint error for {}/{:?}/{:?}",
unit.pkg, unit.mode, unit.target,
);
info!(" err: {e:?}");
}
}
}

match compare {
Ok(None) if forced => Some(DirtyReason::Forced),
Ok(reason) => reason,
Err(_) => Some(DirtyReason::FreshBuild),
}
}

/// If detail is not required, just returns a [`DirtyReason::NothingObvious`]
/// instead of comparing JSON fingerprint files.
fn _compare_old_fingerprint(
old_hash_path: &Path,
new_fingerprint: &Fingerprint,
mtime_on_use: bool,
detail_required: bool,
) -> CargoResult<Option<DirtyReason>> {
let old_fingerprint_short = paths::read(old_hash_path)?;

if mtime_on_use {
// update the mtime so other cleaners know we used it
let t = FileTime::from_system_time(SystemTime::now());
debug!("mtime-on-use forcing {:?} to {}", old_hash_path, t);
paths::set_file_time_no_err(old_hash_path, t);
}

let new_hash = new_fingerprint.hash_u64();

if util::to_hex(new_hash) == old_fingerprint_short && new_fingerprint.fs_status.up_to_date() {
return Ok(None);
}
if !detail_required {
return Ok(Some(DirtyReason::NothingObvious));
}

let old_fingerprint_json = paths::read(&old_hash_path.with_extension("json"))?;
let old_fingerprint: Fingerprint = serde_json::from_str(&old_fingerprint_json)
Expand All @@ -1785,29 +1820,6 @@ fn _compare_old_fingerprint(
Ok(Some(new_fingerprint.compare(&old_fingerprint)))
}

/// Logs the result of fingerprint comparison.
///
/// TODO: Obsolete and mostly superseded by [`DirtyReason`]. Could be removed.
fn log_compare(unit: &Unit, compare: &CargoResult<Option<DirtyReason>>) {
match compare {
Ok(None) => {}
Ok(Some(reason)) => {
info!(
"fingerprint dirty for {}/{:?}/{:?}",
unit.pkg, unit.mode, unit.target,
);
info!(" dirty: {reason:?}");
}
Err(e) => {
info!(
"fingerprint error for {}/{:?}/{:?}",
unit.pkg, unit.mode, unit.target,
);
info!(" err: {e:?}");
}
}
}

/// Parses Cargo's internal [`EncodedDepInfo`] structure that was previously
/// serialized to disk.
///
Expand Down

0 comments on commit fc2352b

Please sign in to comment.