diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f79ec050ba..f1cf427827 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -202,13 +202,13 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-west-1 - name: Configure AWS credentials - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::890664054962:role/ci--rust-lang--rustup aws-region: us-east-1 - name: Deploy build to rustup-builds bucket for release team - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') run: | aws --debug s3 cp --recursive dist s3://rustup-builds/${{ github.sha }}/dist env: @@ -401,13 +401,13 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-west-1 - name: Configure AWS credentials - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::890664054962:role/ci--rust-lang--rustup aws-region: us-east-1 - name: Deploy build to rustup-builds bucket for release team - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') run: | aws --debug s3 cp --recursive dist s3://rustup-builds/${{ github.sha }}/dist env: @@ -606,13 +606,13 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-west-1 - name: Configure AWS credentials - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::890664054962:role/ci--rust-lang--rustup aws-region: us-east-1 - name: Deploy build to rustup-builds bucket for release team - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') run: | aws --debug s3 cp --recursive dist s3://rustup-builds/${{ github.sha }}/dist env: @@ -776,13 +776,13 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-west-1 - name: Configure AWS credentials - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::890664054962:role/ci--rust-lang--rustup aws-region: us-east-1 - name: Deploy build to rustup-builds bucket for release team - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') run: | aws --debug s3 cp --recursive deploy/ s3://rustup-builds/${{ github.sha }} env: @@ -948,13 +948,13 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-west-1 - name: Configure AWS credentials - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::890664054962:role/ci--rust-lang--rustup aws-region: us-east-1 - name: Deploy build to rustup-builds bucket for release team - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') run: | aws --debug s3 cp --recursive deploy/ s3://rustup-builds/${{ github.sha }} env: @@ -1146,13 +1146,13 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-west-1 - name: Configure AWS credentials - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::890664054962:role/ci--rust-lang--rustup aws-region: us-east-1 - name: Deploy build to rustup-builds bucket for release team - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') run: | aws --debug s3 cp --recursive deploy/ s3://rustup-builds/${{ github.sha }} env: @@ -1272,13 +1272,13 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-west-1 - name: Configure AWS credentials - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::890664054962:role/ci--rust-lang--rustup aws-region: us-east-1 - name: Deploy build to rustup-builds bucket for release team - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') run: | aws --debug s3 cp --recursive deploy/ s3://rustup-builds/${{ github.sha }} env: @@ -1403,13 +1403,13 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-west-1 - name: Configure AWS credentials - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::890664054962:role/ci--rust-lang--rustup aws-region: us-east-1 - name: Deploy build to rustup-builds bucket for release team - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') run: | aws --debug s3 cp --recursive deploy/ s3://rustup-builds/${{ github.sha }} env: diff --git a/Cargo.lock b/Cargo.lock index c4ab9ec825..bcb983916e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -232,15 +232,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cc" -version = "1.2.66" +version = "1.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d6cac793997bd970000024b2934968efe83b382de4fdcf4fcb46b6ee4ad996" +checksum = "e17dd265a7d0f31ef544e1b20e03add05d3b45b491b633b10d67145d2acc1a38" dependencies = [ "find-msvc-tools", "jobserver", @@ -442,9 +442,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -452,18 +452,18 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crypto-common" @@ -1267,11 +1267,11 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.3", "libc", ] @@ -1350,9 +1350,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "miniz_oxide" @@ -1515,9 +1515,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-src" -version = "300.5.4+3.5.4" +version = "300.6.1+3.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507b3792995dae9b0df8a1c1e3771e8418b7c2d9f0baeba32e6fe8b06c7cb72" +checksum = "46eb8fb9fb3b61ce1c0f8a026c4c1a0714d3a9e138e7fbde78753ce2babc3846" dependencies = [ "cc", ] @@ -1606,7 +1606,7 @@ dependencies = [ "opentelemetry", "percent-encoding", "portable-atomic", - "rand 0.9.4", + "rand 0.9.5", "thiserror 2.0.18", "tokio", "tokio-stream", @@ -1652,9 +1652,9 @@ checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "platforms" -version = "3.12.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9245c6e7c5a6bcdd7977fdf6d1e1c67f4cc2d0d58c041df0ea5940953033e6ca" +checksum = "acff5dfd42135d89cd7ad74a8c52813bbec91bf62c018ddd89390127767caab5" [[package]] name = "portable-atomic" @@ -1705,7 +1705,7 @@ dependencies = [ "bit-vec", "bitflags", "num-traits", - "rand 0.9.4", + "rand 0.9.5", "rand_chacha", "rand_xorshift", "regex-syntax", @@ -1786,9 +1786,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ "rand_chacha", "rand_core 0.9.5", @@ -1861,9 +1861,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.4" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" dependencies = [ "aho-corasick", "memchr", @@ -1873,9 +1873,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" dependencies = [ "aho-corasick", "memchr", @@ -1951,7 +1951,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cab9bd343c737660e523ee69f788018f3db686d537d2fd0f99c9f747c1bda4f" dependencies = [ - "rand 0.9.4", + "rand 0.9.5", ] [[package]] @@ -2083,7 +2083,6 @@ dependencies = [ "anstyle", "anyhow", "cc", - "cfg-if 1.0.4", "chrono", "clap", "clap-cargo", @@ -2108,7 +2107,6 @@ dependencies = [ "libz-sys", "opener", "openssl", - "openssl-src", "opentelemetry", "opentelemetry-otlp", "opentelemetry_sdk", @@ -2159,9 +2157,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "rusty-fork" @@ -2518,9 +2516,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" dependencies = [ "cfg-if 1.0.4", ] @@ -3316,18 +3314,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.52" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.52" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" dependencies = [ "proc-macro2", "quote", @@ -3396,15 +3394,15 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5431d5661c32445236631278f27946e444ddafe4684cac70b185272d4f9c52d5" +checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5" [[package]] name = "zmij" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "bd2f034a4bebf216c9e4b7083603e024cf930873fd67830cfb083c9fa33129d9" [[package]] name = "zstd" diff --git a/Cargo.toml b/Cargo.toml index 2110cb28d8..5da4af936f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,6 @@ anstream = "1" anstyle = "1.0.11" anyhow = "1.0.69" cc = "1" -cfg-if = "1.0" chrono = { version = "0.4", default-features = false, features = ["std"] } clap = { version = "4", features = ["derive", "wrap_help", "string"] } clap-cargo = "0.18.3" @@ -68,13 +67,10 @@ opener = "0.8.0" # `openssl` is used by `curl` or `reqwest` backend although it isn't imported by rustup: this # allows controlling the vendoring status without exposing the presence of the download crate. openssl = { version = "0.10", optional = true } -# HACK: Temporarily pinned due to ppc64 ELFv1/v2 ABI issue in 300.5.5, to be -# removed when lands. -openssl-src = { version = "=300.5.4", optional = true } opentelemetry = { version = "0.32", optional = true } opentelemetry-otlp = { version = "0.32", features = ["grpc-tonic"], optional = true } opentelemetry_sdk = { version = "0.32", features = ["rt-tokio"], optional = true } -platforms = "3.4" +platforms = "4" pulldown-cmark = { version = "0.13", default-features = false } rand = "0.10" rayon = "1.10.0" @@ -155,7 +151,7 @@ tokio-rustls = "0.26.4" webpki-root-certs = "1" [build-dependencies] -platforms = "3.4" +platforms = "4" [lints.rust] rust_2018_idioms = { level = "deny", priority = -1 } diff --git a/ci/actions-templates/linux-builds-template.yaml b/ci/actions-templates/linux-builds-template.yaml index 214d666fab..ca7d87378d 100644 --- a/ci/actions-templates/linux-builds-template.yaml +++ b/ci/actions-templates/linux-builds-template.yaml @@ -187,13 +187,13 @@ jobs: # skip-main skip-pr skip-stable AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-west-1 - name: Configure AWS credentials - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::890664054962:role/ci--rust-lang--rustup aws-region: us-east-1 - name: Deploy build to rustup-builds bucket for release team - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') run: | aws --debug s3 cp --recursive deploy/ s3://rustup-builds/${{ github.sha }} env: diff --git a/ci/actions-templates/macos-builds-template.yaml b/ci/actions-templates/macos-builds-template.yaml index f7738b8ba0..f6411a929b 100644 --- a/ci/actions-templates/macos-builds-template.yaml +++ b/ci/actions-templates/macos-builds-template.yaml @@ -115,13 +115,13 @@ jobs: # skip-x86_64 skip-aarch64 AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-west-1 - name: Configure AWS credentials - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::890664054962:role/ci--rust-lang--rustup aws-region: us-east-1 - name: Deploy build to rustup-builds bucket for release team - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') run: | aws --debug s3 cp --recursive deploy/ s3://rustup-builds/${{ github.sha }} env: diff --git a/ci/actions-templates/windows-builds-template.yaml b/ci/actions-templates/windows-builds-template.yaml index 60eed06a08..938dd01e12 100644 --- a/ci/actions-templates/windows-builds-template.yaml +++ b/ci/actions-templates/windows-builds-template.yaml @@ -193,13 +193,13 @@ jobs: # skip-main skip-pr skip-stable AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-west-1 - name: Configure AWS credentials - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::890664054962:role/ci--rust-lang--rustup aws-region: us-east-1 - name: Deploy build to rustup-builds bucket for release team - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && matrix.mode == 'release' + if: github.event_name == 'push' && matrix.mode == 'release' && (github.ref == 'refs/heads/stable' || github.ref == 'refs/heads/main') run: | aws --debug s3 cp --recursive dist s3://rustup-builds/${{ github.sha }}/dist env: diff --git a/doc/user-guide/src/concepts/components.md b/doc/user-guide/src/concepts/components.md index 2d9b74beeb..9dce622a9c 100644 --- a/doc/user-guide/src/concepts/components.md +++ b/doc/user-guide/src/concepts/components.md @@ -62,6 +62,8 @@ toolchains. The following is an overview of the different components: * `rustc-dev` --- This component contains the compiler as a library. Most users will not need this; it is only needed for development *of* tools that link to the compiler, such as making modifications to [Clippy]. +* `enzyme` --- This component enables the `std::autodiff` module in nightly Rust. + See [autodiff][enzyme] for more detail. ### Previous components @@ -101,3 +103,4 @@ details. [rustup components history]: https://rust-lang.github.io/rustup-components-history/ [profiles]: profiles.md [nightly availability]: channels.md#nightly-availability +[enzyme]: https://rustc-dev-guide.rust-lang.org/autodiff/installation.html diff --git a/doc/user-guide/src/installation/windows.md b/doc/user-guide/src/installation/windows.md index 59ac3bde82..b9d5d52c40 100644 --- a/doc/user-guide/src/installation/windows.md +++ b/doc/user-guide/src/installation/windows.md @@ -25,13 +25,7 @@ target that tuple by default. You can change this behavior with `rustup set default-host` or during installation. -For example, to explicitly select the 32-bit MSVC host: - -```console -$ rustup set default-host i686-pc-windows-msvc -``` - -Or to choose the 64 bit GNU toolchain: +For example, to choose the 64 bit GNU toolchain: ```console $ rustup set default-host x86_64-pc-windows-gnu diff --git a/src/bin/rustup-init.rs b/src/bin/rustup-init.rs index e844ddc19e..a0d408abc8 100644 --- a/src/bin/rustup-init.rs +++ b/src/bin/rustup-init.rs @@ -16,7 +16,6 @@ use std::process::ExitCode; use anyhow::{Context, Result, anyhow}; -use cfg_if::cfg_if; // Public macros require availability of the internal symbols use rs_tracing::{ close_trace_file, close_trace_file_internal, open_trace_file, trace_to_file_internal, @@ -105,12 +104,9 @@ async fn run_rustup_inner( Some(n) if n.starts_with("rustup-gc-") => { // This is the final uninstallation stage on windows where // rustup deletes its own exe - cfg_if! { - if #[cfg(windows)] { - self_update::complete_windows_uninstall(process) - } else { - unreachable!("Attempted to use Windows-specific code on a non-Windows platform. Aborting.") - } + cfg_select! { + windows => self_update::complete_windows_uninstall(process), + _ => unreachable!("Attempted to use Windows-specific code on a non-Windows platform. Aborting."), } } Some(n) => { diff --git a/src/cli/rustup_mode.rs b/src/cli/rustup_mode.rs index 343eccd504..3dfaa3fc6f 100644 --- a/src/cli/rustup_mode.rs +++ b/src/cli/rustup_mode.rs @@ -468,6 +468,10 @@ struct UpdateOpts { /// Set the installed toolchain as the override for the current directory #[arg(long)] r#override: bool, + + /// Set the installed toolchain as the default toolchain + #[arg(long)] + default: bool, } #[derive(Debug, Default, Args)] @@ -812,7 +816,7 @@ pub async fn main( SelfSubcmd::Uninstall { no_prompt, no_modify_path, - } => self_update::uninstall(no_prompt, no_modify_path, process), + } => self_update::uninstall(no_prompt, no_modify_path, cfg), SelfSubcmd::UpgradeData => cfg.upgrade_data().map(|_| ExitCode::SUCCESS), }, RustupSubcmd::Set { subcmd } => match subcmd { @@ -1040,7 +1044,6 @@ async fn update( let self_update_mode = SelfUpdateMode::from_cfg(cfg)?; let should_self_update = !opts.no_self_update; let force_non_host = opts.force_non_host; - let set_override = opts.r#override; cfg.profile_override = opts.profile; let cfg = &cfg; @@ -1099,11 +1102,13 @@ async fn update( Ok(status.clone()), )?; - if set_override { + if opts.r#override { cfg.make_override(&cfg.current_dir, &desc.clone().into())?; } - if cfg.get_default()?.is_none() && matches!(status, UpdateStatus::Installed) { + if opts.default + || (cfg.get_default()?.is_none() && matches!(status, UpdateStatus::Installed)) + { cfg.set_default(Some(&desc.into()))?; } } diff --git a/src/cli/self_update.rs b/src/cli/self_update.rs index cfe7ef0ed5..374464b86d 100644 --- a/src/cli/self_update.rs +++ b/src/cli/self_update.rs @@ -42,7 +42,6 @@ use std::{fmt, fs}; use anstyle::Style; use anyhow::{Context, Result, anyhow}; -use cfg_if::cfg_if; use clap::ValueEnum; use clap::builder::PossibleValue; use clap_cargo::style::{GOOD, WARN}; @@ -539,12 +538,9 @@ fn canonical_cargo_home(process: &Process) -> Result> { .unwrap_or_else(|| PathBuf::from(".")) .join(".cargo"); Ok(if default_cargo_home == path { - cfg_if! { - if #[cfg(windows)] { - r"%USERPROFILE%\.cargo".into() - } else { - "$HOME/.cargo".into() - } + cfg_select! { + windows => r"%USERPROFILE%\.cargo".into(), + _ => "$HOME/.cargo".into(), } } else { path.to_string_lossy().into_owned().into() @@ -1047,17 +1043,22 @@ async fn maybe_install_rust(opts: InstallOpts<'_>, cfg: &mut Cfg<'_>) -> Result< Ok(()) } -pub(crate) fn uninstall( - no_prompt: bool, - no_modify_path: bool, - process: &Process, -) -> Result { +/// Uninstall process: +/// 1. Remove all installed toolchains. +/// 2. Remove rustup home. +/// 3. Remove all entries in `$CARGO_HOME` except `bin`. +/// 4. Remove rustup tool links and binary. +/// 5. Try to remove $CARGO_HOME/bin directory if it's empty. +/// 6. Upon successfully removing $CARGO_HOME/bin, clean up $PATH. +/// 7. Try to remove $CARGO_HOME directory if it's empty. +pub(crate) fn uninstall(no_prompt: bool, no_modify_path: bool, cfg: &Cfg<'_>) -> Result { if cfg!(feature = "no-self-update") { error!("self-uninstall is disabled for this build of rustup"); error!("you should probably use your system package manager to uninstall rustup"); return Ok(ExitCode::FAILURE); } + let process = cfg.process; let cargo_home = process.cargo_home()?; if !cargo_home.join(format!("bin/rustup{EXE_SUFFIX}")).exists() { @@ -1081,6 +1082,11 @@ pub(crate) fn uninstall( } } + info!("removing toolchains"); + for toolchain in cfg.list_toolchains()? { + Toolchain::ensure_removed(cfg, toolchain.into())?; + } + info!("removing rustup home"); // Delete RUSTUP_HOME diff --git a/src/cli/self_update/unix.rs b/src/cli/self_update/unix.rs index e4e236e2bc..b063f2c462 100644 --- a/src/cli/self_update/unix.rs +++ b/src/cli/self_update/unix.rs @@ -61,10 +61,7 @@ pub(crate) fn do_remove_from_path(process: &Process) -> Result<()> { let file = utils::read_file("rcfile", rc)?; let file_bytes = file.into_bytes(); // FIXME: This is whitespace sensitive where it should not be. - if let Some(idx) = file_bytes - .windows(source_bytes.len()) - .position(|w| w == source_bytes.as_slice()) - { + if let Some(idx) = find_exact_line(&file_bytes, &source_bytes) { // Here we rewrite the file without the offending line. let mut new_bytes = file_bytes[..idx].to_vec(); new_bytes.extend(&file_bytes[idx + source_bytes.len()..]); @@ -153,10 +150,7 @@ fn remove_legacy_source_command(source_cmd: String, process: &Process) -> Result let file = utils::read_file("rcfile", &rc)?; let file_bytes = file.into_bytes(); // FIXME: This is whitespace sensitive where it should not be. - if let Some(idx) = file_bytes - .windows(cmd_bytes.len()) - .position(|w| w == cmd_bytes.as_slice()) - { + if let Some(idx) = find_exact_line(&file_bytes, &cmd_bytes) { // Here we rewrite the file without the offending line. let mut new_bytes = file_bytes[..idx].to_vec(); new_bytes.extend(&file_bytes[idx + cmd_bytes.len()..]); @@ -167,6 +161,16 @@ fn remove_legacy_source_command(source_cmd: String, process: &Process) -> Result Ok(()) } +fn find_exact_line(file: &[u8], line: &[u8]) -> Option { + // The trailing newline enforces the end boundary; check the start boundary here. + assert!(line.ends_with(b"\n")); + file.windows(line.len()) + .enumerate() + .find_map(|(idx, candidate)| { + (candidate == line && (idx == 0 || file[idx - 1] == b'\n')).then_some(idx) + }) +} + fn remove_legacy_paths(process: &Process) -> Result<()> { // Before the work to support more kinds of shells, which was released in // version 1.23.0 of Rustup, we always inserted this line instead, which is diff --git a/src/dist/manifestation.rs b/src/dist/manifestation.rs index 469d830910..9bb2467e52 100644 --- a/src/dist/manifestation.rs +++ b/src/dist/manifestation.rs @@ -29,14 +29,13 @@ use crate::{ config::Config, download::{DownloadCfg, DownloadStatus, File}, manifest::{Component, CompressionKind, HashedBinary, Manifest}, - prefix::InstallPrefix, + prefix::{DIST_MANIFEST, InstallPrefix}, temp, }, errors::RustupError, utils, }; -pub(crate) const DIST_MANIFEST: &str = "multirust-channel-manifest.toml"; pub(crate) const CONFIG_FILE: &str = "multirust-config.toml"; #[derive(Debug)] @@ -396,8 +395,7 @@ impl Manifestation { #[tracing::instrument(level = "trace")] pub fn load_manifest(&self) -> Result> { let prefix = self.installation.prefix(); - let old_manifest_path = prefix.manifest_file(DIST_MANIFEST); - if utils::path_exists(&old_manifest_path) { + if let Some(old_manifest_path) = prefix.dist_manifest() { let manifest_str = utils::read_file("installed manifest", &old_manifest_path)?; Ok(Some(Manifest::parse(&manifest_str).with_context(|| { RustupError::ParsingFile { diff --git a/src/dist/mod.rs b/src/dist/mod.rs index d74afa014c..dc95784dbd 100644 --- a/src/dist/mod.rs +++ b/src/dist/mod.rs @@ -1125,10 +1125,9 @@ async fn try_update_from_dist_( } else { download .dl_v2_manifest( - // Even if manifest has not changed, we must continue to install requested components. - // So if components or targets is not empty, we skip passing `update_hash` so that - // we essentially degenerate to `rustup component add` / `rustup target add` - if components.is_empty() && targets.is_empty() { + // Skip the update hash when the installed manifest is missing or when components + // or targets were requested, since either case still requires the channel manifest. + if prefix.dist_manifest().is_some() && components.is_empty() && targets.is_empty() { Some(update_hash) } else { None diff --git a/src/dist/prefix.rs b/src/dist/prefix.rs index 9b71118017..c0217bfb86 100644 --- a/src/dist/prefix.rs +++ b/src/dist/prefix.rs @@ -11,6 +11,7 @@ const REL_MANIFEST_DIR: &str = match std::path::MAIN_SEPARATOR { }; static V1_COMMON_COMPONENT_LIST: &[&str] = &["cargo", "rustc", "rust-docs"]; +pub(crate) const DIST_MANIFEST: &str = "multirust-channel-manifest.toml"; #[derive(Clone, Debug)] pub struct InstallPrefix { @@ -37,6 +38,11 @@ impl InstallPrefix { path } + pub(crate) fn dist_manifest(&self) -> Option { + let path = self.manifest_file(DIST_MANIFEST); + utils::path_exists(&path).then_some(path) + } + pub(crate) fn rel_manifest_file(&self, name: &str) -> PathBuf { let mut path = PathBuf::from(REL_MANIFEST_DIR); path.push(name); diff --git a/src/dist/target_tuple/known.rs b/src/dist/target_tuple/known.rs index b034a77211..6f46fbfb02 100644 --- a/src/dist/target_tuple/known.rs +++ b/src/dist/target_tuple/known.rs @@ -54,6 +54,7 @@ pub static LIST_ARCHS: &[&str] = &[ "riscv32imac", "riscv32imafc", "riscv32imc", + "riscv32imfc", "riscv64", "riscv64a23", "riscv64gc", @@ -108,9 +109,11 @@ pub static LIST_OSES: &[&str] = &[ "nuttx-eabi", "nuttx-eabihf", "nvidia-cuda", + "oe-linux", "openwrt-linux", "pc-cygwin", "pc-nto", + "pc-qnx", "pc-solaris", "pc-windows", "risc0-zkvm", @@ -138,6 +141,7 @@ pub static LIST_OSES: &[&str] = &[ "unknown-nto", "unknown-nuttx", "unknown-openbsd", + "unknown-qnx", "unknown-qurt", "unknown-redox", "unknown-teeos", @@ -187,10 +191,10 @@ pub static LIST_ENVS: &[&str] = &[ "newlibeabihf", "none", "ohos", + "pauthtest", "qnx700", "qnx710", "qnx710_iosock", - "qnx800", "sgx", "sim", "softfloat", diff --git a/src/settings.rs b/src/settings.rs index 42dc7ceebf..d4e45fbacd 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -29,7 +29,7 @@ impl SettingsFile { fn write_settings(&self) -> Result<()> { let settings = self.cache.borrow(); - utils::write_file( + utils::write_locked_file( "settings", &self.path, &settings.as_ref().unwrap().stringify()?, @@ -44,7 +44,7 @@ impl SettingsFile { if b.is_none() { drop(b); *self.cache.borrow_mut() = Some(if utils::is_file(&self.path) { - let content = utils::read_file("settings", &self.path)?; + let content = utils::read_locked_file("settings", &self.path)?; Settings::parse(&content).with_context(|| RustupError::ParsingFile { name: "settings", path: self.path.clone(), diff --git a/src/toolchain/distributable.rs b/src/toolchain/distributable.rs index a76776fa07..96dfe265d2 100644 --- a/src/toolchain/distributable.rs +++ b/src/toolchain/distributable.rs @@ -439,12 +439,14 @@ impl<'a> DistributableToolchain<'a> { } pub async fn fetch_dist_manifest(&self) -> anyhow::Result> { + let prefix = InstallPrefix::from(self.toolchain.path()); + let update_hash = if prefix.dist_manifest().is_some() { + Some(self.toolchain.cfg.get_hash_file(&self.desc, false)?) + } else { + None + }; DownloadCfg::new(self.toolchain.cfg) - .dl_v2_manifest( - Some(&self.toolchain.cfg.get_hash_file(&self.desc, false)?), - &self.desc, - self.toolchain.cfg, - ) + .dl_v2_manifest(update_hash.as_deref(), &self.desc, self.toolchain.cfg) .await } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index fdb079ccaf..414a5687a4 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -87,6 +87,13 @@ pub fn read_file(name: &'static str, path: &Path) -> Result { }) } +pub(crate) fn read_locked_file(name: &'static str, path: &Path) -> Result { + raw::read_locked_file(path).with_context(|| RustupError::ReadingFile { + name, + path: PathBuf::from(path), + }) +} + pub fn write_file(name: &'static str, path: &Path, contents: &str) -> Result<()> { raw::write_file(path, contents).with_context(|| RustupError::WritingFile { name, @@ -94,6 +101,13 @@ pub fn write_file(name: &'static str, path: &Path, contents: &str) -> Result<()> }) } +pub(crate) fn write_locked_file(name: &'static str, path: &Path, contents: &str) -> Result<()> { + raw::write_locked_file(path, contents).with_context(|| RustupError::WritingFile { + name, + path: PathBuf::from(path), + }) +} + pub(crate) fn append_file(name: &'static str, path: &Path, line: &str) -> Result<()> { raw::append_file(path, line).with_context(|| RustupError::WritingFile { name, diff --git a/src/utils/raw.rs b/src/utils/raw.rs index ba439ae731..70f27f3d42 100644 --- a/src/utils/raw.rs +++ b/src/utils/raw.rs @@ -3,7 +3,7 @@ use std::env; use std::fs; use std::fs::File; use std::io; -use std::io::Write; +use std::io::{Read, Seek, SeekFrom, Write}; use std::path::Path; use std::str; @@ -60,6 +60,21 @@ pub fn path_exists>(path: P) -> bool { fs::metadata(path).is_ok() } +pub(crate) fn read_locked_file(path: &Path) -> io::Result { + let mut file = File::open(path)?; + file.lock_shared()?; + + let size = file + .metadata() + .map(|metadata| usize::try_from(metadata.len()).unwrap_or(usize::MAX)) + .ok(); + let mut contents = String::new(); + contents.try_reserve_exact(size.unwrap_or(0))?; + file.read_to_string(&mut contents)?; + + Ok(contents) +} + pub(crate) fn random_string(length: usize) -> String { const CHARSET: &[u8] = b"abcdefghijklmnopqrstuvwxyz0123456789_"; let mut rng = rand::rng(); @@ -82,6 +97,24 @@ pub fn write_file(path: &Path, contents: &str) -> io::Result<()> { Ok(()) } +pub(crate) fn write_locked_file(path: &Path, contents: &str) -> io::Result<()> { + let mut file = fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + // Truncation must happen after the exclusive lock is held. + .truncate(false) + .open(path)?; + + file.lock()?; + file.set_len(0)?; + file.seek(SeekFrom::Start(0))?; + Write::write_all(&mut file, contents.as_bytes())?; + file.sync_data()?; + + Ok(()) +} + pub(crate) fn filter_file bool>( src: &Path, dest: &Path, @@ -350,3 +383,20 @@ pub(crate) mod windows { inner(s.as_ref()) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn locked_file_round_trip_truncates_previous_contents() -> io::Result<()> { + let temp_dir = tempfile::tempdir()?; + let path = temp_dir.path().join("state.toml"); + + write_locked_file(&path, "last_release_notified_secs = 123456\n")?; + write_locked_file(&path, "version = \"12\"\n")?; + + assert_eq!(read_locked_file(&path)?, "version = \"12\"\n"); + Ok(()) + } +} diff --git a/tests/suite/cli_paths.rs b/tests/suite/cli_paths.rs index f102dd5234..f530619526 100644 --- a/tests/suite/cli_paths.rs +++ b/tests/suite/cli_paths.rs @@ -348,6 +348,41 @@ error: could not amend shell profile[..] } } + #[tokio::test] + async fn install_preserves_guarded_legacy_source() { + let cx = CliTestContext::new(Scenario::Empty).await; + let profile = cx.config.homedir.join(".bash_profile"); + let guarded_source = "[ -f \"$HOME/.cargo/env\" ] && source \"$HOME/.cargo/env\"\n"; + raw::write_file(&profile, guarded_source).unwrap(); + + let mut cmd = cx.config.cmd("rustup-init", &INIT_NONE[1..]); + cmd.env_remove("CARGO_HOME"); + assert!(cmd.output().unwrap().status.success()); + + let new_profile = fs::read_to_string(&profile).unwrap(); + let expected = guarded_source.to_owned() + &source("$HOME/.cargo", POSIX_SH); + assert_eq!(new_profile, expected); + } + + #[tokio::test] + async fn uninstall_preserves_guarded_source() { + let cx = CliTestContext::new(Scenario::Empty).await; + let profile = cx.config.homedir.join(".bash_profile"); + let guarded_source = "[ -f \"$HOME/.cargo/env\" ] && . \"$HOME/.cargo/env\"\n"; + raw::write_file(&profile, guarded_source).unwrap(); + + let mut cmd = cx.config.cmd("rustup-init", &INIT_NONE[1..]); + cmd.env_remove("CARGO_HOME"); + assert!(cmd.output().unwrap().status.success()); + + let mut cmd = cx.config.cmd("rustup", ["self", "uninstall", "-y"]); + cmd.env_remove("CARGO_HOME"); + assert!(cmd.output().unwrap().status.success()); + + let new_profile = fs::read_to_string(&profile).unwrap(); + assert_eq!(new_profile, guarded_source); + } + #[tokio::test] async fn uninstall_cleans_up_legacy_paths() { let cx = CliTestContext::new(Scenario::Empty).await; diff --git a/tests/suite/cli_rustup.rs b/tests/suite/cli_rustup.rs index 91c3891907..76ca060212 100644 --- a/tests/suite/cli_rustup.rs +++ b/tests/suite/cli_rustup.rs @@ -353,7 +353,7 @@ async fn add_target() { let cx = CliTestContext::new(Scenario::SimpleV2).await; let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", - &this_host_tuple(), + this_host_tuple(), CROSS_ARCH1 ); cx.config @@ -372,7 +372,7 @@ async fn remove_target() { let cx = CliTestContext::new(Scenario::SimpleV2).await; let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", - &this_host_tuple(), + this_host_tuple(), CROSS_ARCH1 ); cx.config @@ -404,13 +404,13 @@ async fn add_remove_multiple_targets() { .is_ok(); let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", - &this_host_tuple(), + this_host_tuple(), CROSS_ARCH1 ); assert!(cx.config.rustupdir.has(path)); let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", - &this_host_tuple(), + this_host_tuple(), CROSS_ARCH2 ); assert!(cx.config.rustupdir.has(path)); @@ -421,13 +421,13 @@ async fn add_remove_multiple_targets() { .is_ok(); let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", - &this_host_tuple(), + this_host_tuple(), CROSS_ARCH1 ); assert!(!cx.config.rustupdir.has(path)); let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", - &this_host_tuple(), + this_host_tuple(), CROSS_ARCH2 ); assert!(!cx.config.rustupdir.has(path)); @@ -474,7 +474,7 @@ async fn add_target_explicit() { let cx = CliTestContext::new(Scenario::SimpleV2).await; let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", - &this_host_tuple(), + this_host_tuple(), CROSS_ARCH1 ); cx.config @@ -500,7 +500,7 @@ async fn remove_target_explicit() { let cx = CliTestContext::new(Scenario::SimpleV2).await; let path = format!( "toolchains/nightly-{}/lib/rustlib/{}/lib/libstd.rlib", - &this_host_tuple(), + this_host_tuple(), CROSS_ARCH1 ); cx.config @@ -4173,14 +4173,7 @@ async fn missing_manifest_shows_reinstall_help() { .await .is_ok(); - let manifest_path = cx - .config - .rustupdir - .join("toolchains") - .join(format!("nightly-{}", this_host_tuple())) - .join("lib") - .join("rustlib") - .join("multirust-channel-manifest.toml"); + let manifest_path = nightly_manifest_path(&cx); fs::remove_file(&manifest_path).unwrap(); @@ -4195,3 +4188,51 @@ help: try reinstalling or updating the toolchain "#]]) .is_err(); } + +#[tokio::test] +async fn reinstall_restores_missing_manifest() { + let cx = CliTestContext::new(Scenario::SimpleV2).await; + + cx.config + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); + + let manifest_path = nightly_manifest_path(&cx); + + fs::remove_file(&manifest_path).unwrap(); + + cx.config + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); + + assert!(manifest_path.exists()); +} + +#[tokio::test] +async fn update_all_restores_missing_manifest() { + let cx = CliTestContext::new(Scenario::SimpleV2).await; + + cx.config + .expect(["rustup", "toolchain", "install", "nightly"]) + .await + .is_ok(); + + let manifest_path = nightly_manifest_path(&cx); + fs::remove_file(&manifest_path).unwrap(); + + cx.config.expect(["rustup", "update"]).await.is_ok(); + + assert!(manifest_path.exists()); +} + +fn nightly_manifest_path(cx: &CliTestContext) -> PathBuf { + cx.config + .rustupdir + .join("toolchains") + .join(format!("nightly-{}", this_host_tuple())) + .join("lib") + .join("rustlib") + .join("multirust-channel-manifest.toml") +} diff --git a/tests/suite/cli_rustup_ui/rustup_toolchain_cmd_install_cmd_help_flag.stdout.term.svg b/tests/suite/cli_rustup_ui/rustup_toolchain_cmd_install_cmd_help_flag.stdout.term.svg index f996dc9902..d42f1d8930 100644 --- a/tests/suite/cli_rustup_ui/rustup_toolchain_cmd_install_cmd_help_flag.stdout.term.svg +++ b/tests/suite/cli_rustup_ui/rustup_toolchain_cmd_install_cmd_help_flag.stdout.term.svg @@ -1,4 +1,4 @@ - +