Skip to content

Commit 6df7be3

Browse files
committed
test(build-dir): Added test for workspace-path-hash cross Cargo version consistency
1 parent 662ade8 commit 6df7be3

File tree

2 files changed

+91
-22
lines changed

2 files changed

+91
-22
lines changed

src/cargo/version.rs

+32-22
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,30 @@ pub fn version() -> VersionInfo {
5858
};
5959
}
6060

61-
// This is the version set in bootstrap, which we use to match rustc.
62-
let version = option_env_str!("CFG_RELEASE").unwrap_or_else(|| {
63-
// If cargo is not being built by bootstrap, then we just use the
64-
// version from cargo's own `Cargo.toml`.
65-
//
66-
// There are two versions at play here:
67-
// - version of cargo-the-binary, which you see when you type `cargo --version`
68-
// - version of cargo-the-library, which you download from crates.io for use
69-
// in your packages.
70-
//
71-
// The library is permanently unstable, so it always has a 0 major
72-
// version. However, the CLI now reports a stable 1.x version
73-
// (starting in 1.26) which stays in sync with rustc's version.
74-
//
75-
// Coincidentally, the minor version for cargo-the-library is always
76-
// +1 of rustc's minor version (that is, `rustc 1.11.0` corresponds to
77-
// `cargo `0.12.0`). The versions always get bumped in lockstep, so
78-
// this should continue to hold.
79-
let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap() - 1;
80-
let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u8>().unwrap();
81-
format!("1.{}.{}", minor, patch)
82-
});
61+
let version = version_for_testing()
62+
// This is the version set in bootstrap, which we use to match rustc.
63+
.or_else(|| option_env_str!("CFG_RELEASE"))
64+
.unwrap_or_else(|| {
65+
// If cargo is not being built by bootstrap, then we just use the
66+
// version from cargo's own `Cargo.toml`.
67+
//
68+
// There are two versions at play here:
69+
// - version of cargo-the-binary, which you see when you type `cargo --version`
70+
// - version of cargo-the-library, which you download from crates.io for use
71+
// in your packages.
72+
//
73+
// The library is permanently unstable, so it always has a 0 major
74+
// version. However, the CLI now reports a stable 1.x version
75+
// (starting in 1.26) which stays in sync with rustc's version.
76+
//
77+
// Coincidentally, the minor version for cargo-the-library is always
78+
// +1 of rustc's minor version (that is, `rustc 1.11.0` corresponds to
79+
// `cargo `0.12.0`). The versions always get bumped in lockstep, so
80+
// this should continue to hold.
81+
let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap() - 1;
82+
let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u8>().unwrap();
83+
format!("1.{}.{}", minor, patch)
84+
});
8385

8486
let release_channel = option_env_str!("CFG_RELEASE_CHANNEL");
8587
let commit_info = option_env_str!("CARGO_COMMIT_HASH").map(|commit_hash| CommitInfo {
@@ -96,3 +98,11 @@ pub fn version() -> VersionInfo {
9698
description,
9799
}
98100
}
101+
102+
/// Provides a way for tests to inject an abitrary version for testing purposes.
103+
///
104+
// __CARGO_TEST_CARGO_VERSION should not be relied on outside of tests.
105+
#[allow(clippy::disallowed_methods)]
106+
fn version_for_testing() -> Option<String> {
107+
std::env::var("__CARGO_TEST_CARGO_VERSION").ok()
108+
}

tests/testsuite/build_dir.rs

+59
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,65 @@ fn template_workspace_path_hash() {
609609
assert_exists(&p.root().join(&format!("target-dir/debug/foo{EXE_SUFFIX}")));
610610
}
611611

612+
#[cargo_test]
613+
fn template_workspace_path_hash_should_not_change_between_cargo_versions() {
614+
let p = project()
615+
.file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#)
616+
.file(
617+
"Cargo.toml",
618+
r#"
619+
[package]
620+
name = "foo"
621+
version = "1.0.0"
622+
authors = []
623+
edition = "2015"
624+
"#,
625+
)
626+
.file(
627+
".cargo/config.toml",
628+
r#"
629+
[build]
630+
build-dir = "foo/{workspace-path-hash}/build-dir"
631+
target-dir = "target-dir"
632+
"#,
633+
)
634+
.build();
635+
636+
p.cargo("build -Z build-dir")
637+
.env("__CARGO_TEST_CARGO_VERSION", "1.0.0")
638+
.masquerade_as_nightly_cargo(&["build-dir"])
639+
.enable_mac_dsym()
640+
.run();
641+
642+
let foo_dir = p.root().join("foo");
643+
assert_exists(&foo_dir);
644+
let hash_dir = parse_workspace_manifest_path_hash(&foo_dir);
645+
646+
let first_run_build_dir = hash_dir.as_path().join("build-dir");
647+
assert_build_dir_layout(first_run_build_dir.clone(), "debug");
648+
649+
// Remove the build-dir since we already know the hash and it makes
650+
// finding the directory in the next run simpler.
651+
foo_dir.as_path().rm_rf();
652+
653+
// Run Cargo build again with a different Cargo version
654+
p.cargo("build -Z build-dir")
655+
.env("__CARGO_TEST_CARGO_VERSION", "1.1.0")
656+
.masquerade_as_nightly_cargo(&["build-dir"])
657+
.enable_mac_dsym()
658+
.run();
659+
660+
let hash_dir = parse_workspace_manifest_path_hash(&foo_dir);
661+
let second_run_build_dir = hash_dir.as_path().join("build-dir");
662+
assert_build_dir_layout(second_run_build_dir.clone(), "debug");
663+
664+
// Finally check that the build-dir is in the same location between both Cargo versions
665+
assert_eq!(
666+
first_run_build_dir, second_run_build_dir,
667+
"The workspace path hash generated between 2 Cargo versions did not match"
668+
);
669+
}
670+
612671
fn parse_workspace_manifest_path_hash(hash_dir: &PathBuf) -> PathBuf {
613672
// Since the hash will change between test runs simply find the first directories and assume
614673
// that is the hash dir. The format is a 2 char directory followed by the remaining hash in the

0 commit comments

Comments
 (0)