Skip to content

Commit 7263f3b

Browse files
committed
Add an optimization when running under rustup.
1 parent 18ed848 commit 7263f3b

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

src/cargo/util/config/mod.rs

+42
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,48 @@ impl Config {
16441644
/// as a path.
16451645
fn get_tool(&self, tool: &str, from_config: &Option<ConfigRelativePath>) -> PathBuf {
16461646
self.maybe_get_tool(tool, from_config)
1647+
.or_else(|| {
1648+
// This is an optimization to circumvent the rustup proxies
1649+
// which can have a significant performance hit. The goal here
1650+
// is to determine if calling `rustc` from PATH would end up
1651+
// calling the proxies.
1652+
//
1653+
// This is somewhat cautious trying to determine if it is safe
1654+
// to circumvent rustup, because there are some situations
1655+
// where users may do things like modify PATH, call cargo
1656+
// directly, use a custom rustup toolchain link without a
1657+
// cargo executable, etc. However, there is still some risk
1658+
// this may make the wrong decision in unusual circumstances.
1659+
//
1660+
// First, we must be running under rustup in the first place.
1661+
let toolchain = self.get_env_os("RUSTUP_TOOLCHAIN")?;
1662+
// If the tool on PATH is the same as `rustup` on path, then
1663+
// there is pretty good evidence that it will be a proxy.
1664+
let tool_resolved = paths::resolve_executable(Path::new(tool)).ok()?;
1665+
let rustup_resolved = paths::resolve_executable(Path::new("rustup")).ok()?;
1666+
let tool_meta = tool_resolved.metadata().ok()?;
1667+
let rustup_meta = rustup_resolved.metadata().ok()?;
1668+
// This works on the assumption that rustup and its proxies
1669+
// use hard links to a single binary. If rustup ever changes
1670+
// that setup, then I think the worst consequence is that this
1671+
// optimization will not work, and it will take the slow path.
1672+
if tool_meta.len() != rustup_meta.len() {
1673+
return None;
1674+
}
1675+
// Try to find the tool in rustup's toolchain directory.
1676+
let tool_exe = Path::new(tool).with_extension(env::consts::EXE_EXTENSION);
1677+
let toolchain_exe = home::rustup_home()
1678+
.ok()?
1679+
.join("toolchains")
1680+
.join(&toolchain)
1681+
.join("bin")
1682+
.join(&tool_exe);
1683+
if toolchain_exe.exists() {
1684+
Some(toolchain_exe)
1685+
} else {
1686+
None
1687+
}
1688+
})
16471689
.unwrap_or_else(|| PathBuf::from(tool))
16481690
}
16491691

tests/testsuite/rustup.rs

-2
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ fn typical_rustup() {
165165
.with_stderr(
166166
"\
167167
[CHECKING] foo v0.0.1 [..]
168-
rustc proxy running
169168
real rustc running
170169
[FINISHED] [..]
171170
",
@@ -184,7 +183,6 @@ real rustc running
184183
.with_stderr(
185184
"\
186185
[CHECKING] foo v0.0.1 [..]
187-
rustc proxy running
188186
real rustc running
189187
[FINISHED] [..]
190188
",

0 commit comments

Comments
 (0)