Skip to content
7 changes: 7 additions & 0 deletions docs/lang/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ If not set, it defaults to the profile configured in `rustup`. You can check you
"rust" = { version = "1.83.0", profile = "minimal" }
```

If the Rust toolchain is already installed, `mise install` restores missing components implied by
the `minimal`, `default`, or `complete` profile. Complete-profile membership comes from the
installed toolchain's rustup manifest because it can vary between Rust releases.

Rustup supports only those three named profiles and discourages using `complete`. To customize a
profile, use the `components` and `targets` options with `minimal` or `default`.

### `targets`

The `targets` option specifies platforms to install for cross-compilation. Multiple targets can
Expand Down
165 changes: 154 additions & 11 deletions e2e/core/test_rust_components_reconcile
Original file line number Diff line number Diff line change
Expand Up @@ -22,34 +22,107 @@ cat >"$MISE_CARGO_HOME/bin/rustup" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

host=x86_64-unknown-linux-gnu

echo "$*" >>"$MISE_CARGO_HOME/rustup.log"

case "$1 $2" in
"show profile")
echo default
;;
"show active-toolchain")
[[ ! -f "$MISE_CARGO_HOME/fail-active-toolchain" ]] || exit 1
toolchain="${RUSTUP_TOOLCHAIN:-}"
[[ -d "$MISE_RUSTUP_HOME/toolchains/$toolchain-$host" ]] || exit 1
echo "$toolchain-$host (environment override by RUSTUP_TOOLCHAIN)"
;;
"component list")
toolchain="${*: -1}"
[[ -d "$MISE_RUSTUP_HOME/toolchains/$toolchain" ]] || exit 1
[[ -d "$MISE_RUSTUP_HOME/toolchains/$toolchain-$host" ]] || exit 1
cat "$MISE_CARGO_HOME/components" 2>/dev/null || true
;;
"target list")
toolchain="${*: -1}"
[[ -d "$MISE_RUSTUP_HOME/toolchains/$toolchain" ]] || exit 1
[[ -d "$MISE_RUSTUP_HOME/toolchains/$toolchain-$host" ]] || exit 1
cat "$MISE_CARGO_HOME/targets" 2>/dev/null || true
;;
"toolchain install")
shift 2
toolchain="$1"
shift
toolchain="$toolchain-$host"
toolchain_exists=false
[[ -d "$MISE_RUSTUP_HOME/toolchains/$toolchain" ]] && toolchain_exists=true
mkdir -p "$MISE_RUSTUP_HOME/toolchains/$toolchain"
mkdir -p "$MISE_RUSTUP_HOME/toolchains/$toolchain/lib/rustlib"
cat >"$MISE_RUSTUP_HOME/toolchains/$toolchain/lib/rustlib/multirust-channel-manifest.toml" <<'MANIFEST'
[renames.clippy]
to = "clippy-preview"

[renames.miri]
to = "miri-preview"

[renames.rust-analyzer]
to = "rust-analyzer-preview"

[renames.rustfmt]
to = "rustfmt-preview"

[profiles]
minimal = ["rustc", "cargo", "rust-std"]
default = ["rustc", "cargo", "rust-std", "rust-docs", "rustfmt-preview", "clippy-preview"]
complete = ["rustc", "cargo", "rust-std", "rust-docs", "rustfmt-preview", "clippy-preview", "rust-analyzer-preview", "rust-src", "miri-preview"]

[pkg.rust.target.x86_64-unknown-linux-gnu]

[[pkg.rust.target.x86_64-unknown-linux-gnu.components]]
pkg = "rustc"
target = "x86_64-unknown-linux-gnu"

[[pkg.rust.target.x86_64-unknown-linux-gnu.components]]
pkg = "cargo"
target = "x86_64-unknown-linux-gnu"

[[pkg.rust.target.x86_64-unknown-linux-gnu.components]]
pkg = "rust-std"
target = "x86_64-unknown-linux-gnu"

[[pkg.rust.target.x86_64-unknown-linux-gnu.components]]
pkg = "rust-docs"
target = "x86_64-unknown-linux-gnu"

[[pkg.rust.target.x86_64-unknown-linux-gnu.extensions]]
pkg = "rust-std"
target = "wasm32-unknown-unknown"

[[pkg.rust.target.x86_64-unknown-linux-gnu.extensions]]
pkg = "rustfmt-preview"
target = "x86_64-unknown-linux-gnu"

[[pkg.rust.target.x86_64-unknown-linux-gnu.extensions]]
pkg = "clippy-preview"
target = "x86_64-unknown-linux-gnu"

[[pkg.rust.target.x86_64-unknown-linux-gnu.extensions]]
pkg = "rust-analyzer-preview"
target = "x86_64-unknown-linux-gnu"

[[pkg.rust.target.x86_64-unknown-linux-gnu.extensions]]
pkg = "rust-src"
target = "*"

[[pkg.rust.target.x86_64-unknown-linux-gnu.extensions]]
pkg = "miri-preview"
target = "x86_64-unknown-linux-gnu"
MANIFEST
profile=""
while [[ $# -gt 0 ]]; do
case "$1" in
--component)
echo "$2" >>"$MISE_CARGO_HOME/components"
if [[ "$2" == "rust-src" ]]; then
echo "$2" >>"$MISE_CARGO_HOME/components"
else
echo "$2-$host" >>"$MISE_CARGO_HOME/components"
fi
shift 2
;;
--target)
Expand All @@ -65,8 +138,11 @@ case "$1 $2" in
;;
esac
done
if ! $toolchain_exists && [[ -z "$profile" || "$profile" == "default" ]]; then
printf '%s\n' clippy rust-docs rustfmt >>"$MISE_CARGO_HOME/components"
if ! $toolchain_exists; then
printf '%s\n' "cargo-$host" "rust-std-$host" "rustc-$host" >>"$MISE_CARGO_HOME/components"
if [[ -z "$profile" || "$profile" == "default" || "$profile" == "d" ]]; then
printf '%s\n' "clippy-$host" "rust-docs-$host" "rustfmt-$host" >>"$MISE_CARGO_HOME/components"
fi
fi
sort -u "$MISE_CARGO_HOME/components" -o "$MISE_CARGO_HOME/components" 2>/dev/null || true
sort -u "$MISE_CARGO_HOME/targets" -o "$MISE_CARGO_HOME/targets" 2>/dev/null || true
Expand Down Expand Up @@ -97,13 +173,13 @@ EOF
mise install
assert_contains "grep -c '^toolchain install' '$MISE_CARGO_HOME/rustup.log'" "1"

sed -i '/^rust-docs$/d' "$MISE_CARGO_HOME/components"
sed -i.bak '/^rust-docs-/d' "$MISE_CARGO_HOME/components"
assert_fail_contains "mise install rust --dry-run-code 2>&1" "would install"
mise install
assert_contains "grep -c '^toolchain install' '$MISE_CARGO_HOME/rustup.log'" "2"
assert_contains "cat '$MISE_CARGO_HOME/components'" "rust-docs"

rm -rf "$MISE_RUSTUP_HOME/toolchains/1.81.0"
rm -rf "$MISE_RUSTUP_HOME/toolchains/1.81.0-x86_64-unknown-linux-gnu"
assert_hook_env_does_not_call_rustup
assert_fail_contains "mise install rust --dry-run-code 2>&1" "would install"
mise install
Expand All @@ -114,7 +190,7 @@ cat >mise.toml <<EOF
rust = { version = "1.81.0", profile = "default" }
EOF

sed -i '/^rustfmt$/d' "$MISE_CARGO_HOME/components"
sed -i.bak '/^rustfmt-/d' "$MISE_CARGO_HOME/components"
assert_hook_env_does_not_call_rustup
assert_fail_contains "mise install rust --dry-run-code 2>&1" "would install"
mise install
Expand All @@ -123,6 +199,73 @@ assert_contains "cat '$MISE_CARGO_HOME/components'" "clippy"
assert_contains "cat '$MISE_CARGO_HOME/components'" "rust-docs"
assert_contains "cat '$MISE_CARGO_HOME/components'" "rustfmt"

cat >mise.toml <<EOF
[tools]
rust = { version = "1.81.0", profile = "d" }
EOF

sed -i.bak '/^rustfmt-/d' "$MISE_CARGO_HOME/components"
assert_fail_contains "mise install rust --dry-run-code 2>&1" "would install"
mise install
assert_contains "grep -c '^toolchain install' '$MISE_CARGO_HOME/rustup.log'" "5"
assert_contains "cat '$MISE_CARGO_HOME/components'" "rustfmt"

cat >mise.toml <<EOF
[tools]
rust = { version = "1.81.0", profile = "minimal" }
EOF

printf '%s\n' rust-std-wasm32-unknown-unknown >>"$MISE_CARGO_HOME/components"
sed -i.bak '/^cargo-x86_64-unknown-linux-gnu$/d; /^rustc-x86_64-unknown-linux-gnu$/d; /^rust-std-x86_64-unknown-linux-gnu$/d' \
"$MISE_CARGO_HOME/components"
assert_fail_contains "mise install rust --dry-run-code 2>&1" "would install"
mise install
assert_contains "grep -c '^toolchain install' '$MISE_CARGO_HOME/rustup.log'" "6"
assert_contains "cat '$MISE_CARGO_HOME/components'" "cargo-x86_64-unknown-linux-gnu"
assert_contains "cat '$MISE_CARGO_HOME/components'" "rustc-x86_64-unknown-linux-gnu"
assert_contains "cat '$MISE_CARGO_HOME/components'" "rust-std-x86_64-unknown-linux-gnu"

cat >mise.toml <<EOF
[tools]
rust = { version = "1.81.0", profile = "complete" }
EOF

printf '%s\n' \
cargo-x86_64-unknown-linux-gnu \
clippy-x86_64-unknown-linux-gnu \
miri-x86_64-unknown-linux-gnu \
rust-analyzer-x86_64-unknown-linux-gnu \
rust-docs-x86_64-unknown-linux-gnu \
rust-src \
rust-std-x86_64-unknown-linux-gnu \
rustc-x86_64-unknown-linux-gnu \
rustfmt-x86_64-unknown-linux-gnu >"$MISE_CARGO_HOME/components"
sed -i.bak '/^miri-/d' "$MISE_CARGO_HOME/components"
touch "$MISE_CARGO_HOME/fail-active-toolchain"
assert_fail_contains "mise install rust 2>&1" "active toolchain could not be determined"
assert_contains "grep -c '^toolchain install' '$MISE_CARGO_HOME/rustup.log'" "6"
mv "$MISE_CARGO_HOME/fail-active-toolchain" "$MISE_CARGO_HOME/active-toolchain-recovered"
assert_hook_env_does_not_call_rustup
assert_fail_contains "mise install rust --dry-run-code 2>&1" "would install"
mise install
assert_contains "grep -c '^toolchain install' '$MISE_CARGO_HOME/rustup.log'" "7"
assert_contains "cat '$MISE_CARGO_HOME/components'" "miri-x86_64-unknown-linux-gnu"

manifest="$MISE_RUSTUP_HOME/toolchains/1.81.0-x86_64-unknown-linux-gnu/lib/rustlib/multirust-channel-manifest.toml"
mkdir -p "$PWD/rust-dist/dist"
cp "$manifest" "$PWD/rust-dist/dist/channel-rust-1.81.0.toml"
cat >mise.toml <<EOF
[tools]
rust = { version = "1.81.0", profile = "c", install_env = { RUSTUP_DIST_SERVER = "file://$PWD/rust-dist" } }
EOF

echo 'not valid toml = [' >"$manifest"
sed -i.bak '/^rust-analyzer-/d' "$MISE_CARGO_HOME/components"
assert_fail_contains "mise install rust --dry-run-code 2>&1" "would install"
mise install
assert_contains "grep -c '^toolchain install' '$MISE_CARGO_HOME/rustup.log'" "8"
assert_contains "cat '$MISE_CARGO_HOME/components'" "rust-analyzer-x86_64-unknown-linux-gnu"

cat >mise.toml <<EOF
[tools]
rust = { version = "1.81.0", components = ["rustfmt", "rust-src"], targets = ["wasm32-unknown-unknown"] }
Expand All @@ -131,11 +274,11 @@ EOF
assert_fail_contains "mise install rust --dry-run-code 2>&1" "would install"

mise exec -- rustc -V
assert_contains "grep -c '^toolchain install' '$MISE_CARGO_HOME/rustup.log'" "5"
assert_contains "grep -c '^toolchain install' '$MISE_CARGO_HOME/rustup.log'" "9"
assert_contains "cat '$MISE_CARGO_HOME/components'" "rustfmt"
assert_contains "cat '$MISE_CARGO_HOME/components'" "rust-src"
assert_contains "cat '$MISE_CARGO_HOME/targets'" "wasm32-unknown-unknown"

mise install
assert_contains "grep -c '^toolchain install' '$MISE_CARGO_HOME/rustup.log'" "5"
assert_contains "grep -c '^toolchain install' '$MISE_CARGO_HOME/rustup.log'" "9"
assert_contains "mise install rust --dry-run-code 2>&1" "already installed"
2 changes: 1 addition & 1 deletion e2e/core/test_rust_config_env_homes
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ case "$1 $2" in
echo minimal
;;
"component list")
echo rustfmt
printf '%s\n' cargo rust-std rustc rustfmt
;;
"toolchain install")
mkdir -p "$RUSTUP_HOME/toolchains/$3"
Expand Down
7 changes: 7 additions & 0 deletions e2e/core/test_rust_external_provider
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ mkdir -p "$STATE"
"show profile")
echo minimal
;;
"show active-toolchain")
echo "$RUSTUP_TOOLCHAIN-x86_64-unknown-linux-gnu (environment override)"
;;
"toolchain install")
version=$3
mkdir -p "$STATE/toolchains/$version"
Expand Down Expand Up @@ -55,6 +58,10 @@ mkdir -p "$STATE"
rm -rf "$STATE/toolchains/$3"
;;
"component list")
printf '%s\n' \
cargo-x86_64-unknown-linux-gnu \
rust-std-x86_64-unknown-linux-gnu \
rustc-x86_64-unknown-linux-gnu
cat "$STATE/components" 2>/dev/null || true
;;
"target list")
Expand Down
Loading