Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/cli/proxy_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
command::run_command_for_dir,
config::ActiveReason,
process::Process,
toolchain::ResolvableLocalToolchainName,
toolchain::{ResolvableLocalToolchainName, maybe_set_env_source},
};

#[tracing::instrument(level = "trace", skip(process))]
Expand Down Expand Up @@ -37,7 +37,7 @@ pub async fn main(arg0: &str, current_dir: PathBuf, process: &Process) -> Result
let toolchain = cfg.resolve_local_toolchain(toolchain).await?;
let mut cmd = toolchain.command(arg0)?;
if toolchain_specified {
toolchain.maybe_set_env_source(&mut cmd, || Some(ActiveReason::CommandLine));
maybe_set_env_source(&mut cmd, || Some(ActiveReason::CommandLine));
}
run_command_for_dir(cmd, arg0, &cmd_args)
}
15 changes: 6 additions & 9 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,13 @@ pub(crate) enum ActiveReason {

impl ActiveReason {
/// Format `ActiveReason` for setting the `RUSTUP_TOOLCHAIN_SOURCE` environment variable.
///
/// The format of the variable's content is `source toolchain`. Neither component should
/// contain spaces.
pub fn to_source(&self, name: &LocalToolchainName) -> String {
pub fn to_source(&self) -> &str {
match self {
Self::Default => format!("default {name}"),
Self::Environment => format!("env {name}"),
Self::CommandLine => format!("cli {name}"),
Self::OverrideDB(_) => format!("override {name}"),
Self::ToolchainFile(_) => format!("config {name}"),
Self::Default => "default",
Self::Environment => "env",
Self::CommandLine => "cli",
Self::OverrideDB(_) => "override",
Self::ToolchainFile(_) => "config",
Comment on lines +109 to +113
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is redundant, because the latter component is RUSTUP_TOOLCHAIN. I'll fix this PR in the next few hours.

Huh, RUSTUP_TOOLCHAIN is documented as something the user can set; I didn't realize that rustup sets it on child processes but

cmd.env("RUSTUP_TOOLCHAIN", format!("{}", self.name));

}
}
}
Expand Down
32 changes: 14 additions & 18 deletions src/toolchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ impl<'a> Toolchain<'a> {

env_var::inc("RUST_RECURSION_COUNT", cmd, self.cfg.process);

self.maybe_set_env_source(cmd, || {
maybe_set_env_source(cmd, || {
if let Ok(Some((_, reason))) = self.cfg.active_toolchain() {
Some(reason)
} else {
Expand All @@ -193,23 +193,6 @@ impl<'a> Toolchain<'a> {
cmd.env("RUSTUP_HOME", &self.cfg.rustup_dir);
}

/// Set the `RUSTUP_TOOLCHAIN_SOURCE` environment variable if not already set.
///
/// `RUSTUP_TOOLCHAIN_SOURCE` indicates how the toolchain was determined. The environment
/// variable could have been set in proxy_mode.rs, in which case it should not be changed.
pub(crate) fn maybe_set_env_source(
&self,
cmd: &mut Command,
f: impl FnOnce() -> Option<ActiveReason>,
) {
if env::var_os("RUSTUP_TOOLCHAIN_SOURCE").is_some() {
return;
}
if let Some(reason) = f() {
cmd.env("RUSTUP_TOOLCHAIN_SOURCE", reason.to_source(&self.name));
}
}

/// Apply the appropriate LD path for a command being run from a toolchain.
fn set_ldpath(&self, cmd: &mut Command) {
#[cfg_attr(not(target_os = "macos"), allow(unused_mut))]
Expand Down Expand Up @@ -630,3 +613,16 @@ impl<'a> Toolchain<'a> {
.collect())
}
}

/// Set the `RUSTUP_TOOLCHAIN_SOURCE` environment variable if not already set.
///
/// `RUSTUP_TOOLCHAIN_SOURCE` indicates how the toolchain was determined. The environment
/// variable could have been set in proxy_mode.rs, in which case it should not be changed.
Comment on lines +617 to +620
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we let the original through rather than override it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's the behavior we want.

In my installation, all the proxies link to rustup:

lrwxrwxrwx 1 smoelius smoelius       32 Jan 31  2025 cargo -> /home/smoelius/.cargo/bin/rustup

So I think we want it to handle the + args and we should just let those through:

// Check for a + toolchain specifier
let arg1 = args.next();
let toolchain = arg1
.as_ref()
.map(|arg| arg.to_string_lossy())
.filter(|arg| arg.starts_with('+'))
.map(|name| ResolvableLocalToolchainName::try_from(&name.as_ref()[1..]))
.transpose()?;

I am happy to be corrected if I am misunderstanding.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if run cargo +beta test and one of my tests invokes cargo doc within a directory that has a rustup-toolchain.toml for nightly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RUSTUP_TOOLCHAIN_SOURCE should be set to cli. But I don't think I understand the point of your question.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within the cargo doc call, the source of the toolchain is config but RUSTUP_TOOLCHAIN_SOURCE will incorrectly report back cli because the outer most rustup call had it set on the CLI.

To me, it seems like we should only inherit RUSTUP_TOOLCHAIN_SOURCE if we are inheriting the parent's toolchain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within the cargo doc call, the source of the toolchain is config

I don't mean to question you but are you sure that's right?

I just tested in a configuration like you described with this program:

//! ```
//! let stdout = std::process::Command::new("env").output().unwrap().stdout;
//! std::fs::write("env.txt", stdout).unwrap();
//! ```

#[test]
fn test() {
    std::process::Command::new("cargo").arg("doc").status().unwrap();
}

And here is what I saw written to the env.txt file:

RUSTUP_HOME=/home/smoelius/.rustup
RUSTUP_TOOLCHAIN=beta-x86_64-unknown-linux-gnu
RUSTUP_TOOLCHAIN_SOURCE=cli

If I run with just cargo test instead of cargo +beta test, I observe what you describe.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I run with just cargo test instead of cargo +beta test, I observe what you describe.

So my exact example didn't work but the principle still applies.

pub(crate) fn maybe_set_env_source(cmd: &mut Command, f: impl FnOnce() -> Option<ActiveReason>) {
if env::var_os("RUSTUP_TOOLCHAIN_SOURCE").is_some() {
return;
}
if let Some(reason) = f() {
cmd.env("RUSTUP_TOOLCHAIN_SOURCE", reason.to_source());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or is that only env variables that rustup reads?

Are the ones it sets defined anywhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think both are in that list. I updated the list.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in rust-lang/cargo#11036, RUSTUP_TOOLCHAIN_SOURCE could be taken as pointing to something inside the toolchain or pointing to what caused the toolchain to be set, not just the kind of toolchain source.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I take your point. But I thought we wanted to let the rustup team decide on the variable name. So I have tried to remain agnostic on that front.

}
}
10 changes: 5 additions & 5 deletions tests/suite/cli_rustup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3050,7 +3050,7 @@ async fn rustup_toolchain_source_cli() {
.await
.with_stderr(snapbox::str![[r#"
...
cli nightly-[HOST_TRIPLE]
cli

"#]]);
}
Expand All @@ -3066,7 +3066,7 @@ async fn rustup_toolchain_source_env() {
.await
.with_stderr(snapbox::str![[r#"
...
env nightly-[HOST_TRIPLE]
env

"#]]);
}
Expand All @@ -3083,7 +3083,7 @@ async fn rustup_toolchain_source_override() {
.await
.with_stderr(snapbox::str![[r#"
...
override nightly-[HOST_TRIPLE]
override

"#]]);
}
Expand All @@ -3098,7 +3098,7 @@ async fn rustup_toolchain_source_config() {
.await
.with_stderr(snapbox::str![[r#"
...
config nightly-[HOST_TRIPLE]
config

"#]]);
}
Expand All @@ -3115,7 +3115,7 @@ async fn rustup_toolchain_source_default() {
.await
.with_stderr(snapbox::str![[r#"
...
default stable-[HOST_TRIPLE]
default

"#]]);
}
Expand Down