Skip to content

Commit

Permalink
Simple explanations for why cargo rebuilds crates
Browse files Browse the repository at this point in the history
  • Loading branch information
dnbln committed Dec 28, 2022
1 parent 5a574d3 commit 0beb5fe
Show file tree
Hide file tree
Showing 17 changed files with 768 additions and 150 deletions.
144 changes: 143 additions & 1 deletion crates/cargo-test-support/src/compare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
//! `[WARNING]`) to match cargo's "status" output and allows you to ignore
//! the alignment. See the source of `substitute_macros` for a complete list
//! of substitutions.
//! - `[DIRTY-MSVC]` (only when the line starts with it) would be replaced by
//! `[DIRTY]` when `cfg(target_env = "msvc")` or the line will be ignored otherwise.
//! Tests that work around [issue 7358](https://github.com/rust-lang/cargo/issues/7358)
//! can use this to avoid duplicating the `with_stderr` call like:
//! `if cfg!(target_env = "msvc") {e.with_stderr("...[DIRTY]...");} else {e.with_stderr("...");}`.
//!
//! # Normalization
//!
Expand Down Expand Up @@ -108,7 +113,9 @@ fn normalize_actual(actual: &str, cwd: Option<&Path>) -> String {

/// Normalizes the expected string so that it can be compared against the actual output.
fn normalize_expected(expected: &str, cwd: Option<&Path>) -> String {
let expected = substitute_macros(expected);
let expected = replace_dirty_msvc(expected);
let expected = substitute_macros(&expected);

if cfg!(windows) {
normalize_windows(&expected, cwd)
} else {
Expand All @@ -121,6 +128,29 @@ fn normalize_expected(expected: &str, cwd: Option<&Path>) -> String {
}
}

fn replace_dirty_msvc_impl(s: &str, is_msvc: bool) -> String {
if is_msvc {
s.replace("[DIRTY-MSVC]", "[DIRTY]")
} else {
use itertools::Itertools;

let mut new = s
.lines()
.filter(|it| !it.starts_with("[DIRTY-MSVC]"))
.join("\n");

if s.ends_with("\n") {
new.push_str("\n");
}

new
}
}

fn replace_dirty_msvc(s: &str) -> String {
replace_dirty_msvc_impl(s, cfg!(target_env = "msvc"))
}

/// Normalizes text for both actual and expected strings on Windows.
fn normalize_windows(text: &str, cwd: Option<&Path>) -> String {
// Let's not deal with / vs \ (windows...)
Expand Down Expand Up @@ -170,6 +200,7 @@ fn substitute_macros(input: &str) -> String {
("[DOCUMENTING]", " Documenting"),
("[SCRAPING]", " Scraping"),
("[FRESH]", " Fresh"),
("[DIRTY]", " Dirty"),
("[UPDATING]", " Updating"),
("[ADDING]", " Adding"),
("[REMOVING]", " Removing"),
Expand Down Expand Up @@ -637,3 +668,114 @@ fn wild_str_cmp() {
assert_ne!(WildStr::new(a), WildStr::new(b));
}
}

#[test]
fn dirty_msvc() {
let case = |expected: &str, wild: &str, msvc: bool| {
assert_eq!(expected, &replace_dirty_msvc_impl(wild, msvc));
};

// no replacements
case("aa", "aa", false);
case("aa", "aa", true);

// with replacements
case(
"\
[DIRTY] a",
"\
[DIRTY-MSVC] a",
true,
);
case(
"",
"\
[DIRTY-MSVC] a",
false,
);
case(
"\
[DIRTY] a
[COMPILING] a",
"\
[DIRTY-MSVC] a
[COMPILING] a",
true,
);
case(
"\
[COMPILING] a",
"\
[DIRTY-MSVC] a
[COMPILING] a",
false,
);

// test trailing newline behavior
case(
"\
A
B
", "\
A
B
", true,
);

case(
"\
A
B
", "\
A
B
", false,
);

case(
"\
A
B", "\
A
B", true,
);

case(
"\
A
B", "\
A
B", false,
);

case(
"\
[DIRTY] a
",
"\
[DIRTY-MSVC] a
",
true,
);
case(
"\n",
"\
[DIRTY-MSVC] a
",
false,
);

case(
"\
[DIRTY] a",
"\
[DIRTY-MSVC] a",
true,
);
case(
"",
"\
[DIRTY-MSVC] a",
false,
);
}
6 changes: 3 additions & 3 deletions src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::job::{Freshness, Job, Work};
use super::job::{Job, Work};
use super::{fingerprint, Context, LinkType, Unit};
use crate::core::compiler::artifact;
use crate::core::compiler::context::Metadata;
Expand Down Expand Up @@ -484,11 +484,11 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
});

let mut job = if cx.bcx.build_config.build_plan {
Job::new_dirty(Work::noop())
Job::new_dirty(Work::noop(), None)
} else {
fingerprint::prepare_target(cx, unit, false)?
};
if job.freshness() == Freshness::Dirty {
if job.freshness().is_dirty() {
job.before(dirty);
} else {
job.before(fresh);
Expand Down
Loading

0 comments on commit 0beb5fe

Please sign in to comment.