Skip to content

Commit 5c31ec3

Browse files
committed
Improve config.toml vs config symlink check on Unix
The code attempts to suppress the warning if `config` is merely a symlink to `config.toml`. But it does this by calling readlink and comparing the result textually. That's not ideal because it depends on the precise spelling (`config.toml` vs `./config.toml` vs `/path/to/config.toml`) and also minds whether it's config.toml -> config, or v.v. On Unix, where we can get st_dev and st_ino, use that to suppress the check when the two names resolve to the same underlying file.
1 parent ea23780 commit 5c31ec3

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

src/cargo/util/context/mod.rs

+23
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,29 @@ impl GlobalContext {
15451545
// WITH an extension, which people may want to do to
15461546
// support multiple Cargo versions at once and not
15471547
// get a warning.
1548+
1549+
// On Unix we can see if the two files are the same by using stat(2),
1550+
// and comparing the inode numbers. That way it doesn't matter precisely
1551+
// what spelling the link uses to refers to the other file (relative
1552+
// vs absolute pathname, etc.) Also, this is symmetrical: it doesn't mind
1553+
// which way round the symlink is.
1554+
#[cfg(unix)]
1555+
let skip_warning = if let (Ok(metadata_1), Ok(metadata_2)) = (
1556+
fs::metadata(&possible),
1557+
fs::metadata(&possible_with_extension),
1558+
) {
1559+
use std::os::unix::fs::MetadataExt;
1560+
let devino = |md: fs::Metadata| (md.dev(), md.ino());
1561+
devino(metadata_1) == devino(metadata_2)
1562+
} else {
1563+
false
1564+
};
1565+
1566+
// Platforms other than unix don't have std::os::unix::fs::MetadataExt
1567+
// and its st_ino and st_dev methods. We can still ignore a symlink,
1568+
// but only based on its *contents*, which we must hope are identical
1569+
// to our computed pathname.
1570+
#[cfg(not(unix))]
15481571
let skip_warning = if let Ok(target_path) = fs::read_link(&possible) {
15491572
target_path == possible_with_extension ||
15501573
// allow `config` -> `config.toml`, without the parent dir(s),

0 commit comments

Comments
 (0)