mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00
Added symlink resolution for workspace-path-hash
(#15400)
### What does this PR try to resolve? This PR adds logic to resolve symlinks before hashing the `workspace-path-hash` template variable for `build.build-dir`. See https://github.com/rust-lang/cargo/issues/14125#issuecomment-2751658701 cc: #14125 Note: The behavior on unix systems is unchanged, as the manifest_path was already canonicalized (at least on my system and in CI). However, the Windows behavior did not do this previous. ### How should we test and review this PR? I added a test which runs `cargo build` twice, once from the real directory and once from inside of a symlinked directory, then verifies that hashes match. The change is only a few lines. Most of the diffs are testing code r? @epage
This commit is contained in:
commit
7ade57b15f
@ -672,7 +672,8 @@ impl GlobalContext {
|
|||||||
.to_string(),
|
.to_string(),
|
||||||
),
|
),
|
||||||
("{workspace-path-hash}", {
|
("{workspace-path-hash}", {
|
||||||
let hash = crate::util::hex::short_hash(&workspace_manifest_path);
|
let real_path = std::fs::canonicalize(workspace_manifest_path)?;
|
||||||
|
let hash = crate::util::hex::short_hash(&real_path);
|
||||||
format!("{}{}{}", &hash[0..2], std::path::MAIN_SEPARATOR, &hash[2..])
|
format!("{}{}{}", &hash[0..2], std::path::MAIN_SEPARATOR, &hash[2..])
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use cargo_test_support::prelude::*;
|
|
||||||
use cargo_test_support::{paths, project, str};
|
use cargo_test_support::{paths, project, str};
|
||||||
|
use cargo_test_support::{prelude::*, Project};
|
||||||
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX, EXE_SUFFIX};
|
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX, EXE_SUFFIX};
|
||||||
|
|
||||||
#[cargo_test]
|
#[cargo_test]
|
||||||
@ -569,7 +569,7 @@ fn template_cargo_cache_home() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cargo_test]
|
#[cargo_test]
|
||||||
fn template_workspace_manfiest_path_hash() {
|
fn template_workspace_path_hash() {
|
||||||
let p = project()
|
let p = project()
|
||||||
.file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#)
|
.file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#)
|
||||||
.file(
|
.file(
|
||||||
@ -609,6 +609,81 @@ fn template_workspace_manfiest_path_hash() {
|
|||||||
assert_exists(&p.root().join(&format!("target-dir/debug/foo{EXE_SUFFIX}")));
|
assert_exists(&p.root().join(&format!("target-dir/debug/foo{EXE_SUFFIX}")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verify that the {workspace-path-hash} does not changes if cargo is run from inside of
|
||||||
|
/// a symlinked directory.
|
||||||
|
/// The test approach is to build a project twice from the non-symlinked directory and a symlinked
|
||||||
|
/// directory and then compare the build-dir paths.
|
||||||
|
#[cargo_test]
|
||||||
|
fn template_workspace_path_hash_should_handle_symlink() {
|
||||||
|
#[cfg(unix)]
|
||||||
|
use std::os::unix::fs::symlink;
|
||||||
|
#[cfg(windows)]
|
||||||
|
use std::os::windows::fs::symlink_dir as symlink;
|
||||||
|
|
||||||
|
let p = project()
|
||||||
|
.file("src/lib.rs", "")
|
||||||
|
.file(
|
||||||
|
"Cargo.toml",
|
||||||
|
r#"
|
||||||
|
[package]
|
||||||
|
name = "foo"
|
||||||
|
version = "1.0.0"
|
||||||
|
authors = []
|
||||||
|
edition = "2015"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.file(
|
||||||
|
".cargo/config.toml",
|
||||||
|
r#"
|
||||||
|
[build]
|
||||||
|
build-dir = "foo/{workspace-path-hash}/build-dir"
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Build from the non-symlinked directory
|
||||||
|
p.cargo("check -Z build-dir")
|
||||||
|
.masquerade_as_nightly_cargo(&["build-dir"])
|
||||||
|
.enable_mac_dsym()
|
||||||
|
.run();
|
||||||
|
|
||||||
|
// Parse and verify the hash dir created from the non-symlinked dir
|
||||||
|
let foo_dir = p.root().join("foo");
|
||||||
|
assert_exists(&foo_dir);
|
||||||
|
let original_hash_dir = parse_workspace_manifest_path_hash(&foo_dir);
|
||||||
|
verify_layouts(&p, &original_hash_dir);
|
||||||
|
|
||||||
|
// Create a symlink of the project root.
|
||||||
|
let mut symlinked_dir = p.root().clone();
|
||||||
|
symlinked_dir.pop();
|
||||||
|
symlinked_dir = symlinked_dir.join("symlink-dir");
|
||||||
|
symlink(p.root(), &symlinked_dir).unwrap();
|
||||||
|
|
||||||
|
// Remove the foo dir (which contains the build-dir) before we rebuild from a symlinked dir.
|
||||||
|
foo_dir.rm_rf();
|
||||||
|
|
||||||
|
// Run cargo from the symlinked dir
|
||||||
|
p.cargo("check -Z build-dir")
|
||||||
|
.cwd(&symlinked_dir)
|
||||||
|
.masquerade_as_nightly_cargo(&["build-dir"])
|
||||||
|
.enable_mac_dsym()
|
||||||
|
.run();
|
||||||
|
|
||||||
|
// Parse and verify the hash created from the symlinked dir
|
||||||
|
assert_exists(&foo_dir);
|
||||||
|
let symlink_hash_dir = parse_workspace_manifest_path_hash(&foo_dir);
|
||||||
|
verify_layouts(&p, &symlink_hash_dir);
|
||||||
|
|
||||||
|
// Verify the hash dir created from the symlinked and non-symlinked dirs are the same.
|
||||||
|
assert_eq!(original_hash_dir, symlink_hash_dir);
|
||||||
|
|
||||||
|
fn verify_layouts(p: &Project, build_dir_parent: &PathBuf) {
|
||||||
|
let build_dir = build_dir_parent.as_path().join("build-dir");
|
||||||
|
assert_build_dir_layout(build_dir, "debug");
|
||||||
|
assert_artifact_dir_layout(p.root().join("target"), "debug");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_workspace_manifest_path_hash(hash_dir: &PathBuf) -> PathBuf {
|
fn parse_workspace_manifest_path_hash(hash_dir: &PathBuf) -> PathBuf {
|
||||||
// Since the hash will change between test runs simply find the first directories and assume
|
// Since the hash will change between test runs simply find the first directories and assume
|
||||||
// that is the hash dir. The format is a 2 char directory followed by the remaining hash in the
|
// that is the hash dir. The format is a 2 char directory followed by the remaining hash in the
|
||||||
|
Loading…
x
Reference in New Issue
Block a user