summaryrefslogtreecommitdiffstats
path: root/src/tools/cargo
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/cargo')
-rw-r--r--src/tools/cargo/.github/renovate.json527
-rw-r--r--src/tools/cargo/.github/workflows/main.yml11
-rw-r--r--src/tools/cargo/CHANGELOG.md176
-rw-r--r--src/tools/cargo/Cargo.lock819
-rw-r--r--src/tools/cargo/Cargo.toml74
-rw-r--r--src/tools/cargo/benches/benchsuite/Cargo.toml1
-rw-r--r--src/tools/cargo/benches/benchsuite/benches/resolve.rs8
-rw-r--r--src/tools/cargo/benches/capture/Cargo.toml1
-rw-r--r--src/tools/cargo/clippy.toml8
-rw-r--r--src/tools/cargo/crates/cargo-platform/Cargo.toml2
-rw-r--r--src/tools/cargo/crates/cargo-platform/examples/matches.rs4
-rw-r--r--src/tools/cargo/crates/cargo-platform/src/error.rs4
-rw-r--r--src/tools/cargo/crates/cargo-platform/src/lib.rs3
-rw-r--r--src/tools/cargo/crates/cargo-test-macro/Cargo.toml1
-rw-r--r--src/tools/cargo/crates/cargo-test-macro/src/lib.rs2
-rw-r--r--src/tools/cargo/crates/cargo-test-support/Cargo.toml5
-rw-r--r--src/tools/cargo/crates/cargo-test-support/src/compare.rs1
-rw-r--r--src/tools/cargo/crates/cargo-test-support/src/diff.rs48
-rw-r--r--src/tools/cargo/crates/cargo-test-support/src/git.rs21
-rw-r--r--src/tools/cargo/crates/cargo-test-support/src/lib.rs77
-rw-r--r--src/tools/cargo/crates/cargo-test-support/src/publish.rs7
-rw-r--r--src/tools/cargo/crates/cargo-test-support/src/registry.rs44
-rw-r--r--src/tools/cargo/crates/cargo-util/Cargo.toml3
-rw-r--r--src/tools/cargo/crates/cargo-util/src/paths.rs31
-rw-r--r--src/tools/cargo/crates/crates-io/Cargo.toml3
-rw-r--r--src/tools/cargo/crates/crates-io/lib.rs12
-rw-r--r--src/tools/cargo/crates/mdman/Cargo.toml1
-rw-r--r--src/tools/cargo/crates/mdman/src/format/mod.rs (renamed from src/tools/cargo/crates/mdman/src/format.rs)0
-rw-r--r--src/tools/cargo/crates/mdman/src/hbs.rs12
-rw-r--r--src/tools/cargo/crates/mdman/src/lib.rs2
-rw-r--r--src/tools/cargo/crates/mdman/src/main.rs19
-rw-r--r--src/tools/cargo/crates/resolver-tests/Cargo.toml2
-rw-r--r--src/tools/cargo/crates/resolver-tests/src/lib.rs30
-rw-r--r--src/tools/cargo/crates/resolver-tests/tests/resolve.rs33
-rw-r--r--src/tools/cargo/crates/semver-check/Cargo.toml1
-rw-r--r--src/tools/cargo/crates/semver-check/src/main.rs4
-rw-r--r--src/tools/cargo/crates/xtask-build-man/Cargo.toml1
-rw-r--r--src/tools/cargo/crates/xtask-bump-check/Cargo.toml1
-rw-r--r--src/tools/cargo/crates/xtask-bump-check/src/main.rs1
-rw-r--r--src/tools/cargo/crates/xtask-bump-check/src/xtask.rs12
-rw-r--r--src/tools/cargo/crates/xtask-stale-label/Cargo.toml1
-rw-r--r--src/tools/cargo/credential/cargo-credential-1password/Cargo.toml2
-rw-r--r--src/tools/cargo/credential/cargo-credential-1password/README.md17
-rw-r--r--src/tools/cargo/credential/cargo-credential-1password/src/main.rs4
-rw-r--r--src/tools/cargo/credential/cargo-credential-libsecret/Cargo.toml2
-rw-r--r--src/tools/cargo/credential/cargo-credential-libsecret/README.md6
-rw-r--r--src/tools/cargo/credential/cargo-credential-libsecret/src/lib.rs10
-rw-r--r--src/tools/cargo/credential/cargo-credential-macos-keychain/Cargo.toml2
-rw-r--r--src/tools/cargo/credential/cargo-credential-macos-keychain/README.md7
-rw-r--r--src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml2
-rw-r--r--src/tools/cargo/credential/cargo-credential-wincred/README.md6
-rw-r--r--src/tools/cargo/credential/cargo-credential-wincred/src/lib.rs4
-rw-r--r--src/tools/cargo/credential/cargo-credential/Cargo.toml3
-rw-r--r--src/tools/cargo/credential/cargo-credential/README.md4
-rw-r--r--src/tools/cargo/credential/cargo-credential/examples/file-provider.rs4
-rw-r--r--src/tools/cargo/credential/cargo-credential/examples/stdout-redirected.rs4
-rw-r--r--src/tools/cargo/credential/cargo-credential/src/error.rs4
-rw-r--r--src/tools/cargo/credential/cargo-credential/src/lib.rs204
-rw-r--r--src/tools/cargo/deny.toml4
-rwxr-xr-xsrc/tools/cargo/publish.py16
-rw-r--r--src/tools/cargo/src/bin/cargo/cli.rs87
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/add.rs12
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/bench.rs18
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/build.rs7
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/check.rs6
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/clean.rs8
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/doc.rs6
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/fetch.rs6
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/fix.rs6
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/generate_lockfile.rs4
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/init.rs6
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/install.rs134
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/locate_project.rs4
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/login.rs22
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/logout.rs19
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/metadata.rs4
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/new.rs6
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/owner.rs12
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/package.rs8
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/pkgid.rs4
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/publish.rs18
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/read_manifest.rs8
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/remove.rs14
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/report.rs6
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/run.rs6
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/rustc.rs6
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/rustdoc.rs6
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/search.rs13
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/test.rs22
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/tree.rs6
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/uninstall.rs4
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/update.rs54
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/vendor.rs54
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/verify_project.rs4
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/version.rs4
-rw-r--r--src/tools/cargo/src/bin/cargo/commands/yank.rs13
-rw-r--r--src/tools/cargo/src/bin/cargo/main.rs17
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/build_config.rs6
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/build_context/mod.rs10
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/build_context/target_info.rs26
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/build_plan.rs5
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/compilation.rs53
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/context/compilation_files.rs2
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/context/mod.rs2
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/custom_build.rs55
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/fingerprint/mod.rs64
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/future_incompat.rs32
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/job_queue/mod.rs5
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/links.rs5
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/mod.rs61
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/standard_lib.rs4
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/timings.rs18
-rw-r--r--src/tools/cargo/src/cargo/core/compiler/unit_dependencies.rs26
-rw-r--r--src/tools/cargo/src/cargo/core/dependency.rs42
-rw-r--r--src/tools/cargo/src/cargo/core/features.rs52
-rw-r--r--src/tools/cargo/src/cargo/core/manifest.rs12
-rw-r--r--src/tools/cargo/src/cargo/core/mod.rs4
-rw-r--r--src/tools/cargo/src/cargo/core/package.rs31
-rw-r--r--src/tools/cargo/src/cargo/core/package_id.rs51
-rw-r--r--src/tools/cargo/src/cargo/core/package_id_spec.rs224
-rw-r--r--src/tools/cargo/src/cargo/core/profiles.rs20
-rw-r--r--src/tools/cargo/src/cargo/core/registry.rs7
-rw-r--r--src/tools/cargo/src/cargo/core/resolver/dep_cache.rs63
-rw-r--r--src/tools/cargo/src/cargo/core/resolver/encode.rs25
-rw-r--r--src/tools/cargo/src/cargo/core/resolver/errors.rs223
-rw-r--r--src/tools/cargo/src/cargo/core/resolver/features.rs150
-rw-r--r--src/tools/cargo/src/cargo/core/resolver/mod.rs28
-rw-r--r--src/tools/cargo/src/cargo/core/resolver/types.rs2
-rw-r--r--src/tools/cargo/src/cargo/core/resolver/version_prefs.rs3
-rw-r--r--src/tools/cargo/src/cargo/core/shell.rs186
-rw-r--r--src/tools/cargo/src/cargo/core/source_id.rs (renamed from src/tools/cargo/src/cargo/core/source/source_id.rs)191
-rw-r--r--src/tools/cargo/src/cargo/core/summary.rs11
-rw-r--r--src/tools/cargo/src/cargo/core/workspace.rs48
-rw-r--r--src/tools/cargo/src/cargo/lib.rs37
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_add/mod.rs108
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_clean.rs389
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_compile/mod.rs23
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_fetch.rs5
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_generate_lockfile.rs57
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_install.rs89
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_new.rs15
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_output_metadata.rs9
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_package.rs17
-rw-r--r--src/tools/cargo/src/cargo/ops/cargo_pkgid.rs5
-rw-r--r--src/tools/cargo/src/cargo/ops/common_for_install_and_uninstall.rs4
-rw-r--r--src/tools/cargo/src/cargo/ops/fix.rs25
-rw-r--r--src/tools/cargo/src/cargo/ops/lockfile.rs4
-rw-r--r--src/tools/cargo/src/cargo/ops/mod.rs1
-rw-r--r--src/tools/cargo/src/cargo/ops/registry/login.rs15
-rw-r--r--src/tools/cargo/src/cargo/ops/registry/logout.rs5
-rw-r--r--src/tools/cargo/src/cargo/ops/registry/mod.rs39
-rw-r--r--src/tools/cargo/src/cargo/ops/registry/owner.rs8
-rw-r--r--src/tools/cargo/src/cargo/ops/registry/publish.rs35
-rw-r--r--src/tools/cargo/src/cargo/ops/registry/search.rs23
-rw-r--r--src/tools/cargo/src/cargo/ops/registry/yank.rs13
-rw-r--r--src/tools/cargo/src/cargo/ops/resolve.rs77
-rw-r--r--src/tools/cargo/src/cargo/ops/tree/graph.rs5
-rw-r--r--src/tools/cargo/src/cargo/ops/tree/mod.rs6
-rw-r--r--src/tools/cargo/src/cargo/sources/config.rs37
-rw-r--r--src/tools/cargo/src/cargo/sources/directory.rs11
-rw-r--r--src/tools/cargo/src/cargo/sources/git/mod.rs2
-rw-r--r--src/tools/cargo/src/cargo/sources/git/oxide.rs2
-rw-r--r--src/tools/cargo/src/cargo/sources/git/source.rs9
-rw-r--r--src/tools/cargo/src/cargo/sources/git/utils.rs27
-rw-r--r--src/tools/cargo/src/cargo/sources/mod.rs14
-rw-r--r--src/tools/cargo/src/cargo/sources/path.rs15
-rw-r--r--src/tools/cargo/src/cargo/sources/registry/download.rs1
-rw-r--r--src/tools/cargo/src/cargo/sources/registry/http_remote.rs51
-rw-r--r--src/tools/cargo/src/cargo/sources/registry/index.rs260
-rw-r--r--src/tools/cargo/src/cargo/sources/registry/local.rs2
-rw-r--r--src/tools/cargo/src/cargo/sources/registry/mod.rs38
-rw-r--r--src/tools/cargo/src/cargo/sources/registry/remote.rs14
-rw-r--r--src/tools/cargo/src/cargo/sources/replaced.rs6
-rw-r--r--src/tools/cargo/src/cargo/sources/source.rs (renamed from src/tools/cargo/src/cargo/core/source/mod.rs)22
-rw-r--r--src/tools/cargo/src/cargo/util/auth/mod.rs215
-rw-r--r--src/tools/cargo/src/cargo/util/command_prelude.rs135
-rw-r--r--src/tools/cargo/src/cargo/util/config/de.rs5
-rw-r--r--src/tools/cargo/src/cargo/util/config/key.rs2
-rw-r--r--src/tools/cargo/src/cargo/util/config/mod.rs154
-rw-r--r--src/tools/cargo/src/cargo/util/config/target.rs1
-rw-r--r--src/tools/cargo/src/cargo/util/config/value.rs19
-rw-r--r--src/tools/cargo/src/cargo/util/credential/paseto.rs13
-rw-r--r--src/tools/cargo/src/cargo/util/credential/process.rs67
-rw-r--r--src/tools/cargo/src/cargo/util/dependency_queue.rs5
-rw-r--r--src/tools/cargo/src/cargo/util/flock.rs11
-rw-r--r--src/tools/cargo/src/cargo/util/graph.rs148
-rw-r--r--src/tools/cargo/src/cargo/util/interning.rs34
-rw-r--r--src/tools/cargo/src/cargo/util/mod.rs14
-rw-r--r--src/tools/cargo/src/cargo/util/network/http.rs14
-rw-r--r--src/tools/cargo/src/cargo/util/network/mod.rs2
-rw-r--r--src/tools/cargo/src/cargo/util/network/retry.rs62
-rw-r--r--src/tools/cargo/src/cargo/util/network/sleep.rs1
-rw-r--r--src/tools/cargo/src/cargo/util/profile.rs5
-rw-r--r--src/tools/cargo/src/cargo/util/progress.rs10
-rw-r--r--src/tools/cargo/src/cargo/util/rustc.rs3
-rw-r--r--src/tools/cargo/src/cargo/util/semver_ext.rs213
-rw-r--r--src/tools/cargo/src/cargo/util/style.rs13
-rw-r--r--src/tools/cargo/src/cargo/util/to_semver.rs5
-rw-r--r--src/tools/cargo/src/cargo/util/toml/embedded.rs193
-rw-r--r--src/tools/cargo/src/cargo/util/toml/mod.rs531
-rw-r--r--src/tools/cargo/src/cargo/util/toml/targets.rs11
-rw-r--r--src/tools/cargo/src/doc/book.toml1
-rw-r--r--src/tools/cargo/src/doc/contrib/src/SUMMARY.md1
-rw-r--r--src/tools/cargo/src/doc/contrib/src/implementation/debugging.md6
-rw-r--r--src/tools/cargo/src/doc/contrib/src/process/security.md136
-rw-r--r--src/tools/cargo/src/doc/man/cargo-add.md6
-rw-r--r--src/tools/cargo/src/doc/man/cargo-bench.md16
-rw-r--r--src/tools/cargo/src/doc/man/cargo-build.md5
-rw-r--r--src/tools/cargo/src/doc/man/cargo-check.md5
-rw-r--r--src/tools/cargo/src/doc/man/cargo-clean.md10
-rw-r--r--src/tools/cargo/src/doc/man/cargo-doc.md5
-rw-r--r--src/tools/cargo/src/doc/man/cargo-fetch.md7
-rw-r--r--src/tools/cargo/src/doc/man/cargo-fix.md5
-rw-r--r--src/tools/cargo/src/doc/man/cargo-install.md5
-rw-r--r--src/tools/cargo/src/doc/man/cargo-login.md25
-rw-r--r--src/tools/cargo/src/doc/man/cargo-logout.md12
-rw-r--r--src/tools/cargo/src/doc/man/cargo-metadata.md2
-rw-r--r--src/tools/cargo/src/doc/man/cargo-package.md7
-rw-r--r--src/tools/cargo/src/doc/man/cargo-publish.md12
-rw-r--r--src/tools/cargo/src/doc/man/cargo-remove.md5
-rw-r--r--src/tools/cargo/src/doc/man/cargo-run.md3
-rw-r--r--src/tools/cargo/src/doc/man/cargo-rustc.md5
-rw-r--r--src/tools/cargo/src/doc/man/cargo-rustdoc.md5
-rw-r--r--src/tools/cargo/src/doc/man/cargo-test.md15
-rw-r--r--src/tools/cargo/src/doc/man/cargo-tree.md5
-rw-r--r--src/tools/cargo/src/doc/man/cargo-update.md18
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-bench.txt12
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-build.txt8
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-check.txt8
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-clean.txt5
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-doc.txt8
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-fix.txt8
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-install.txt8
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-login.txt26
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-logout.txt13
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-metadata.txt2
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-package.txt8
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-publish.txt16
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-run.txt8
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-rustc.txt8
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-rustdoc.txt8
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-test.txt8
-rw-r--r--src/tools/cargo/src/doc/man/generated_txt/cargo-update.txt28
-rw-r--r--src/tools/cargo/src/doc/man/includes/options-keep-going.md9
-rw-r--r--src/tools/cargo/src/doc/src/SUMMARY.md2
-rw-r--r--src/tools/cargo/src/doc/src/appendix/glossary.md44
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-add.md3
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-bench.md15
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-build.md10
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-check.md10
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-clean.md7
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-doc.md10
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-fetch.md3
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-fix.md10
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-install.md10
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-login.md25
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-logout.md12
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-metadata.md2
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-package.md11
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-publish.md17
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-remove.md2
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-run.md9
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-rustc.md10
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-rustdoc.md10
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-test.md11
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-tree.md2
-rw-r--r--src/tools/cargo/src/doc/src/commands/cargo-update.md19
-rw-r--r--src/tools/cargo/src/doc/src/faq.md92
-rw-r--r--src/tools/cargo/src/doc/src/getting-started/first-steps.md4
-rw-r--r--src/tools/cargo/src/doc/src/getting-started/index.md2
-rw-r--r--src/tools/cargo/src/doc/src/getting-started/installation.md6
-rw-r--r--src/tools/cargo/src/doc/src/guide/build-cache.md6
-rw-r--r--src/tools/cargo/src/doc/src/guide/cargo-home.md2
-rw-r--r--src/tools/cargo/src/doc/src/guide/cargo-toml-vs-cargo-lock.md19
-rw-r--r--src/tools/cargo/src/doc/src/guide/continuous-integration.md79
-rw-r--r--src/tools/cargo/src/doc/src/guide/creating-a-new-project.md2
-rw-r--r--src/tools/cargo/src/doc/src/guide/dependencies.md4
-rw-r--r--src/tools/cargo/src/doc/src/guide/index.md2
-rw-r--r--src/tools/cargo/src/doc/src/guide/project-layout.md2
-rw-r--r--src/tools/cargo/src/doc/src/guide/tests.md2
-rw-r--r--src/tools/cargo/src/doc/src/guide/why-cargo-exists.md6
-rw-r--r--src/tools/cargo/src/doc/src/guide/working-on-an-existing-project.md2
-rw-r--r--src/tools/cargo/src/doc/src/index.md3
-rw-r--r--src/tools/cargo/src/doc/src/reference/build-script-examples.md12
-rw-r--r--src/tools/cargo/src/doc/src/reference/build-scripts.md50
-rw-r--r--src/tools/cargo/src/doc/src/reference/cargo-targets.md42
-rw-r--r--src/tools/cargo/src/doc/src/reference/config.md272
-rw-r--r--src/tools/cargo/src/doc/src/reference/credential-provider-protocol.md237
-rw-r--r--src/tools/cargo/src/doc/src/reference/environment-variables.md20
-rw-r--r--src/tools/cargo/src/doc/src/reference/external-tools.md16
-rw-r--r--src/tools/cargo/src/doc/src/reference/features-examples.md20
-rw-r--r--src/tools/cargo/src/doc/src/reference/features.md34
-rw-r--r--src/tools/cargo/src/doc/src/reference/future-incompat-report.md2
-rw-r--r--src/tools/cargo/src/doc/src/reference/index.md2
-rw-r--r--src/tools/cargo/src/doc/src/reference/manifest.md97
-rw-r--r--src/tools/cargo/src/doc/src/reference/overriding-dependencies.md20
-rw-r--r--src/tools/cargo/src/doc/src/reference/pkgid-spec.md12
-rw-r--r--src/tools/cargo/src/doc/src/reference/profiles.md52
-rw-r--r--src/tools/cargo/src/doc/src/reference/publishing.md35
-rw-r--r--src/tools/cargo/src/doc/src/reference/registries.md14
-rw-r--r--src/tools/cargo/src/doc/src/reference/registry-authentication.md111
-rw-r--r--src/tools/cargo/src/doc/src/reference/registry-index.md45
-rw-r--r--src/tools/cargo/src/doc/src/reference/registry-web-api.md25
-rw-r--r--src/tools/cargo/src/doc/src/reference/resolver.md6
-rw-r--r--src/tools/cargo/src/doc/src/reference/running-a-registry.md2
-rw-r--r--src/tools/cargo/src/doc/src/reference/semver.md37
-rw-r--r--src/tools/cargo/src/doc/src/reference/source-replacement.md10
-rw-r--r--src/tools/cargo/src/doc/src/reference/specifying-dependencies.md81
-rw-r--r--src/tools/cargo/src/doc/src/reference/timings.md2
-rw-r--r--src/tools/cargo/src/doc/src/reference/unstable.md634
-rw-r--r--src/tools/cargo/src/doc/src/reference/workspaces.md48
-rw-r--r--src/tools/cargo/src/etc/_cargo16
-rw-r--r--src/tools/cargo/src/etc/cargo.bashcomp.sh16
-rw-r--r--src/tools/cargo/src/etc/man/cargo-bench.113
-rw-r--r--src/tools/cargo/src/etc/man/cargo-build.19
-rw-r--r--src/tools/cargo/src/etc/man/cargo-check.19
-rw-r--r--src/tools/cargo/src/etc/man/cargo-clean.16
-rw-r--r--src/tools/cargo/src/etc/man/cargo-doc.19
-rw-r--r--src/tools/cargo/src/etc/man/cargo-fix.19
-rw-r--r--src/tools/cargo/src/etc/man/cargo-install.19
-rw-r--r--src/tools/cargo/src/etc/man/cargo-login.131
-rw-r--r--src/tools/cargo/src/etc/man/cargo-logout.112
-rw-r--r--src/tools/cargo/src/etc/man/cargo-metadata.12
-rw-r--r--src/tools/cargo/src/etc/man/cargo-package.19
-rw-r--r--src/tools/cargo/src/etc/man/cargo-publish.119
-rw-r--r--src/tools/cargo/src/etc/man/cargo-run.19
-rw-r--r--src/tools/cargo/src/etc/man/cargo-rustc.19
-rw-r--r--src/tools/cargo/src/etc/man/cargo-rustdoc.19
-rw-r--r--src/tools/cargo/src/etc/man/cargo-test.112
-rw-r--r--src/tools/cargo/src/etc/man/cargo-update.119
-rw-r--r--src/tools/cargo/tests/testsuite/alt_registry.rs7
-rw-r--r--src/tools/cargo/tests/testsuite/artifact_dep.rs140
-rw-r--r--src/tools/cargo/tests/testsuite/bad_config.rs152
-rw-r--r--src/tools/cargo/tests/testsuite/bench.rs18
-rw-r--r--src/tools/cargo/tests/testsuite/build.rs37
-rw-r--r--src/tools/cargo/tests/testsuite/build_script.rs37
-rw-r--r--src/tools/cargo/tests/testsuite/cargo/help/stdout.log5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/in/Cargo.toml5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/in/src/lib.rs (renamed from src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/README.md)0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/mod.rs38
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/out/Cargo.toml8
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/stderr.log5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/stdout.log (renamed from src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stdout.log)0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/in/Cargo.toml5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/mod.rs38
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/out/Cargo.toml8
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/stderr.log34
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/invalid_manifest/stderr.log3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/mod.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_alias_config.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_bench/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_bench/mod.rs1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/in/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/mod.rs19
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/stderr.log7
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_build/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_check/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_clean/help/stdout.log3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_config/mod.rs22
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_doc/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_features.rs7
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_fetch/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_fix/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/clean-glob1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/ignore-glob1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_init/help/stdout.log7
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/out/.ignore1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_install/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_login/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/help/stdout.log7
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_lints/mod.rs4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/mod.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/Cargo.toml (renamed from src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/Cargo.toml)0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/README.md0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/src/lib.rs (renamed from src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/src/lib.rs)0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/mod.rs (renamed from src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/mod.rs)0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/Cargo.toml (renamed from src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/Cargo.toml)0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/foo/Cargo.toml (renamed from src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/Cargo.toml)0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/foo/src/main.rs (renamed from src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/src/main.rs)0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/src/lib.rs (renamed from src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/src/lib.rs)0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/stderr.log (renamed from src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stderr.log)0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_owner/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_package/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_publish/help/stdout.log8
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_remove/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_remove/mod.rs1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/in/Cargo.toml13
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/in/src/lib.rs1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/mod.rs25
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/out/Cargo.toml10
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/stderr.log1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_run/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_rustc/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_search/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_test/help/stdout.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_test/mod.rs1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/in/Cargo.toml3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/in/src/lib.rs0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/mod.rs19
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/stderr.log7
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_tree/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_update/help/stdout.log12
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_update/mod.rs1
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/in/Cargo.toml5
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/in/src/main.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/mod.rs19
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/stderr.log2
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/stdout.log0
-rw-r--r--src/tools/cargo/tests/testsuite/cargo_yank/help/stdout.log4
-rw-r--r--src/tools/cargo/tests/testsuite/check.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/clean.rs201
-rw-r--r--src/tools/cargo/tests/testsuite/config.rs24
-rw-r--r--src/tools/cargo/tests/testsuite/config_cli.rs10
-rw-r--r--src/tools/cargo/tests/testsuite/credential_process.rs262
-rw-r--r--src/tools/cargo/tests/testsuite/doc.rs4
-rw-r--r--src/tools/cargo/tests/testsuite/features2.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/freshness.rs4
-rw-r--r--src/tools/cargo/tests/testsuite/future_incompat_report.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/git.rs29
-rw-r--r--src/tools/cargo/tests/testsuite/inheritable_workspace_fields.rs8
-rw-r--r--src/tools/cargo/tests/testsuite/install.rs51
-rw-r--r--src/tools/cargo/tests/testsuite/install_upgrade.rs8
-rw-r--r--src/tools/cargo/tests/testsuite/lints.rs197
-rw-r--r--src/tools/cargo/tests/testsuite/list_availables.rs39
-rw-r--r--src/tools/cargo/tests/testsuite/login.rs16
-rw-r--r--src/tools/cargo/tests/testsuite/logout.rs23
-rw-r--r--src/tools/cargo/tests/testsuite/lto.rs6
-rw-r--r--src/tools/cargo/tests/testsuite/metadata.rs21
-rw-r--r--src/tools/cargo/tests/testsuite/new.rs4
-rw-r--r--src/tools/cargo/tests/testsuite/offline.rs4
-rw-r--r--src/tools/cargo/tests/testsuite/owner.rs8
-rw-r--r--src/tools/cargo/tests/testsuite/patch.rs48
-rw-r--r--src/tools/cargo/tests/testsuite/pkgid.rs131
-rw-r--r--src/tools/cargo/tests/testsuite/profile_config.rs4
-rw-r--r--src/tools/cargo/tests/testsuite/profile_custom.rs4
-rw-r--r--src/tools/cargo/tests/testsuite/profile_overrides.rs54
-rw-r--r--src/tools/cargo/tests/testsuite/profiles.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/publish.rs47
-rw-r--r--src/tools/cargo/tests/testsuite/registry.rs67
-rw-r--r--src/tools/cargo/tests/testsuite/registry_auth.rs23
-rw-r--r--src/tools/cargo/tests/testsuite/replace.rs158
-rw-r--r--src/tools/cargo/tests/testsuite/run.rs37
-rw-r--r--src/tools/cargo/tests/testsuite/rust_version.rs253
-rw-r--r--src/tools/cargo/tests/testsuite/rustdocflags.rs8
-rw-r--r--src/tools/cargo/tests/testsuite/script.rs37
-rw-r--r--src/tools/cargo/tests/testsuite/search.rs9
-rw-r--r--src/tools/cargo/tests/testsuite/source_replacement.rs47
-rw-r--r--src/tools/cargo/tests/testsuite/ssh.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/test.rs18
-rw-r--r--src/tools/cargo/tests/testsuite/tool_paths.rs88
-rw-r--r--src/tools/cargo/tests/testsuite/tree.rs2
-rw-r--r--src/tools/cargo/tests/testsuite/update.rs257
-rw-r--r--src/tools/cargo/tests/testsuite/workspaces.rs3
-rw-r--r--src/tools/cargo/tests/testsuite/yank.rs8
-rw-r--r--src/tools/cargo/triagebot.toml8
466 files changed, 8948 insertions, 4904 deletions
diff --git a/src/tools/cargo/.github/renovate.json5 b/src/tools/cargo/.github/renovate.json5
index 8ad9952d2..b633fc245 100644
--- a/src/tools/cargo/.github/renovate.json5
+++ b/src/tools/cargo/.github/renovate.json5
@@ -8,7 +8,34 @@
ignorePaths: [
"**/tests/**",
],
+ customManagers: [
+ {
+ customType: 'regex',
+ fileMatch: [
+ '^Cargo.toml$',
+ ],
+ matchStrings: [
+ 'rust-version.*?(?<currentValue>\\d+\\.\\d+(\\.\\d+)?)',
+ ],
+ depNameTemplate: 'latest-msrv',
+ packageNameTemplate: 'rust-lang/rust',
+ datasourceTemplate: 'github-releases',
+ },
+ ],
packageRules: [
+ {
+ commitMessageTopic: 'Latest MSRV',
+ matchManagers: [
+ 'regex',
+ ],
+ matchPackageNames: [
+ 'latest-msrv',
+ ],
+ "extractVersion": "^(?<version>\\d+\\.\\d+)", // Drop the patch version
+ schedule: [
+ '* * * * *',
+ ],
+ },
// Goals:
// - Rollup safe upgrades to reduce CI runner load
// - Have lockfile and manifest in-sync (implicit rules)
diff --git a/src/tools/cargo/.github/workflows/main.yml b/src/tools/cargo/.github/workflows/main.yml
index 2e71f14b8..44dd76e13 100644
--- a/src/tools/cargo/.github/workflows/main.yml
+++ b/src/tools/cargo/.github/workflows/main.yml
@@ -20,6 +20,7 @@ jobs:
needs:
- build_std
- clippy
+ - credential_msrv
- docs
- lockfile
- resolver
@@ -37,6 +38,7 @@ jobs:
needs:
- build_std
- clippy
+ - credential_msrv
- docs
- lockfile
- resolver
@@ -176,7 +178,7 @@ jobs:
run: 'cargo test -p cargo --test testsuite -- fix::'
env:
__CARGO_TEST_FORCE_ARGFILE: 1
- - run: cargo test --workspace --exclude cargo --exclude benchsuite
+ - run: cargo test --workspace --exclude cargo --exclude benchsuite --exclude resolver-tests
- name: Check benchmarks
run: |
# This only tests one benchmark since it can take over 10 minutes to
@@ -246,3 +248,10 @@ jobs:
cd target
curl -sSLO https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh
sh linkcheck.sh --all --path ../src/doc cargo
+
+ credential_msrv:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - run: rustup update 1.70 && rustup default 1.70
+ - run: cargo test -p cargo-credential
diff --git a/src/tools/cargo/CHANGELOG.md b/src/tools/cargo/CHANGELOG.md
index 0141302c8..f2c9bd0eb 100644
--- a/src/tools/cargo/CHANGELOG.md
+++ b/src/tools/cargo/CHANGELOG.md
@@ -1,23 +1,110 @@
# Changelog
+## Cargo 1.74 (2023-11-16)
+[80eca0e5...HEAD](https://github.com/rust-lang/cargo/compare/80eca0e5...HEAD)
+
+### Added
+
+### Changed
+
+### Fixed
+
+### Nightly only
+
+### Documentation
+
+- âť— Policy change: Checking `Cargo.lock` into version control is now the default choice,
+ even for libraries. Lockfile and CI integration documentations are also expanded.
+ [Policy docs](https://doc.rust-lang.org/nightly/cargo/faq.html#why-have-cargolock-in-version-control),
+ [Lockfile docs](https://doc.rust-lang.org/nightly/cargo/guide/cargo-toml-vs-cargo-lock.html),
+ [CI docs](https://doc.rust-lang.org/nightly/cargo/guide/continuous-integration.html),
+ [#12382](https://github.com/rust-lang/cargo/pull/12382)
+
## Cargo 1.73 (2023-10-05)
-[45782b6b...HEAD](https://github.com/rust-lang/cargo/compare/45782b6b...HEAD)
+[45782b6b...rust-1.73.0](https://github.com/rust-lang/cargo/compare/45782b6b...rust-1.73.0)
### Added
+- Print environment variables for `cargo run/bench/test` in extra verbose mode `-vv`.
+ [#12498](https://github.com/rust-lang/cargo/pull/12498)
+- Display package versions on Cargo timings graph.
+ [#12420](https://github.com/rust-lang/cargo/pull/12420)
+
### Changed
+- Cargo now bails out when using `cargo::` in custom build scripts. This is
+ a preparation for an upcoming change in build script invocations.
+ [#12332](https://github.com/rust-lang/cargo/pull/12332)
+- Make Cargo `--help` easier to browse.
+ [#11905](https://github.com/rust-lang/cargo/pull/11905)
+- Prompt the use of `--nocapture` flag if `cargo test` process is terminated via a signal.
+ [#12463](https://github.com/rust-lang/cargo/pull/12463)
+- Preserve jobserver file descriptors on the rustc invocation for getting target information.
+ [#12447](https://github.com/rust-lang/cargo/pull/12447)
+- Clarify in `--help` that `cargo test --all-targets` excludes doctests.
+ [#12422](https://github.com/rust-lang/cargo/pull/12422)
+- Normalize `cargo.toml` to `Cargo.toml` on publish, and warn on other cases of `Cargo.toml`.
+ [#12399](https://github.com/rust-lang/cargo/pull/12399)
+
### Fixed
+- Only skip mtime check on `~/.cargo/{git,registry}`.
+ [#12369](https://github.com/rust-lang/cargo/pull/12369)
+- Fixed `cargo doc --open` crash on WSL2.
+ [#12373](https://github.com/rust-lang/cargo/pull/12373)
+- Fixed panic when enabling `http.debug` for certain strings.
+ [#12468](https://github.com/rust-lang/cargo/pull/12468)
+- Fixed `cargo remove` incorrectly removing used patches.
+ [#12454](https://github.com/rust-lang/cargo/pull/12454)
+- Fixed crate checksum lookup query should match on semver build metadata.
+ [#11447](https://github.com/rust-lang/cargo/pull/11447)
+- Fixed printing multiple warning messages for unused fields in `[registries]` table.
+ [#12439](https://github.com/rust-lang/cargo/pull/12439)
+
### Nightly only
+- 🔥 The `-Zcredential-process` has been reimplemented with a clearer way to
+ communicate with different credential providers. Several built-in providers
+ are also added to Cargo.
+ [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#credential-process)
+ [#12334](https://github.com/rust-lang/cargo/pull/12334)
+ [#12396](https://github.com/rust-lang/cargo/pull/12396)
+ [#12424](https://github.com/rust-lang/cargo/pull/12424)
+ [#12440](https://github.com/rust-lang/cargo/pull/12440)
+ [#12461](https://github.com/rust-lang/cargo/pull/12461)
+ [#12469](https://github.com/rust-lang/cargo/pull/12469)
+ [#12483](https://github.com/rust-lang/cargo/pull/12483)
+ [#12499](https://github.com/rust-lang/cargo/pull/12499)
+ [#12507](https://github.com/rust-lang/cargo/pull/12507)
+ [#12512](https://github.com/rust-lang/cargo/pull/12512)
+ [#12518](https://github.com/rust-lang/cargo/pull/12518)
+ [#12521](https://github.com/rust-lang/cargo/pull/12521)
+ [#12526](https://github.com/rust-lang/cargo/pull/12526)
+ Some notable changes:
+ - Renamed `credential-process` to `credential-provider` in Cargo configurations.
+ - New JSON protocol for communicating with external credential providers via stdin/stdout.
+ - The GNOME Secert provider now dynamically loads `libsecert`.
+ - The 1password provider is no longer built-in.
+ - Changed the unstable key for asymmetric tokens from `registry-auth` to `credential-process`.
+- ❗️ Removed `--keep-going` flag support from `cargo test` and `cargo bench`.
+ [#12478](https://github.com/rust-lang/cargo/pull/12478)
+ [#12492](https://github.com/rust-lang/cargo/pull/12492)
- Fixed invalid package names generated by `-Zscript`.
[#12349](https://github.com/rust-lang/cargo/pull/12349)
- `-Zscript` now errors out on unsupported commands — `publish` and `package`.
[#12350](https://github.com/rust-lang/cargo/pull/12350)
+- Encode URL params correctly for source ID in Cargo.lock.
+ [#12280](https://github.com/rust-lang/cargo/pull/12280)
+- Replaced invalid `panic_unwind` std feature with `panic-unwind`.
+ [#12364](https://github.com/rust-lang/cargo/pull/12364)
+- `-Zlints`: doctest extraction should respect `[lints]`.
+ [#12501](https://github.com/rust-lang/cargo/pull/12501)
### Documentation
+- SemVer: Adding a section for changing the alignment, layout, or size of a
+ well-defined type.
+ [#12169](https://github.com/rust-lang/cargo/pull/12169)
- Use heading attributes to control the fragment.
[#12339](https://github.com/rust-lang/cargo/pull/12339)
- Use "number" instead of "digit" when explaining Cargo's use of semver.
@@ -26,19 +113,66 @@
[#12344](https://github.com/rust-lang/cargo/pull/12344)
- Clarify "Package ID" and "Source ID" in `cargo metadata` are opaque strings.
[#12313](https://github.com/rust-lang/cargo/pull/12313)
-- Added `profile.strip` to configuration docs.
- [#12337](https://github.com/rust-lang/cargo/pull/12337)
-- Multiple versions that differ only in the metadata tag are disallowed on crates.io.
+- Clarify that `rerun-if-env-changed` doesn't monitor the environment variables
+ it set for crates and build script.
+ [#12482](https://github.com/rust-lang/cargo/pull/12482)
+- Clarify that multiple versions that differ only in the metadata tag are
+ disallowed on crates.io.
[#12335](https://github.com/rust-lang/cargo/pull/12335)
+- Clarify `lto` setting passing `-Clinker-plugin-lto`.
+ [#12407](https://github.com/rust-lang/cargo/pull/12407)
+- Added `profile.strip` to configuration and environment variable docs.
+ [#12337](https://github.com/rust-lang/cargo/pull/12337)
+ [#12408](https://github.com/rust-lang/cargo/pull/12408)
+- Added docs for artifact JSON debuginfo levels.
+ [#12376](https://github.com/rust-lang/cargo/pull/12376)
+- Added a notice for the backward compatible `.cargo/credential` file existence.
+ [#12479](https://github.com/rust-lang/cargo/pull/12479)
+- Raised the awareness of `resolver = 2` used inside workspaces.
+ [#12388](https://github.com/rust-lang/cargo/pull/12388)
+- Replaced `master` branch by default branch in documentation.
+ [#12435](https://github.com/rust-lang/cargo/pull/12435)
### Internal
- Updated to `criterion` 0.5.1.
[#12338](https://github.com/rust-lang/cargo/pull/12338)
+- Updated to `curl-sys` 0.4.65, which corresponds to curl 8.2.1.
+ [#12406](https://github.com/rust-lang/cargo/pull/12406)
+- Updated to `indexmap` v2.
+ [#12368](https://github.com/rust-lang/cargo/pull/12368)
+- Updated to `miow` 0.6.0, which drops old versions of `windows-sys`.
+ [#12453](https://github.com/rust-lang/cargo/pull/12453)
- ci: automatically test new packages by using `--workspace`.
[#12342](https://github.com/rust-lang/cargo/pull/12342)
- ci: automatically update dependencies monthly with Renovate.
[#12341](https://github.com/rust-lang/cargo/pull/12341)
+ [#12466](https://github.com/rust-lang/cargo/pull/12466)
+- ci: rewrote `xtask-bump-check` for respecting semver by adopting `cargo-semver-checks`.
+ [#12395](https://github.com/rust-lang/cargo/pull/12395)
+ [#12513](https://github.com/rust-lang/cargo/pull/12513)
+ [#12508](https://github.com/rust-lang/cargo/pull/12508)
+- Rearranged and renamed test directories
+ [#12397](https://github.com/rust-lang/cargo/pull/12397)
+ [#12398](https://github.com/rust-lang/cargo/pull/12398)
+- Migrated from `log` to `tracing`.
+ [#12458](https://github.com/rust-lang/cargo/pull/12458)
+ [#12488](https://github.com/rust-lang/cargo/pull/12488)
+- Track `--help` output in tests.
+ [#11912](https://github.com/rust-lang/cargo/pull/11912)
+- Cleaned up and shared package metadata within workspace.
+ [#12352](https://github.com/rust-lang/cargo/pull/12352)
+- `crates-io`: expose HTTP headers and `Error` type.
+ [#12310](https://github.com/rust-lang/cargo/pull/12310)
+- For `cargo update`, caught CLI flags conflict between `--aggressive` and `--precise` in clap.
+ [#12428](https://github.com/rust-lang/cargo/pull/12428)
+- Several fixes for either making Cargo testsuite pass on nightly or in `rust-lang/rust`.
+ [#12413](https://github.com/rust-lang/cargo/pull/12413)
+ [#12416](https://github.com/rust-lang/cargo/pull/12416)
+ [#12429](https://github.com/rust-lang/cargo/pull/12429)
+ [#12450](https://github.com/rust-lang/cargo/pull/12450)
+ [#12491](https://github.com/rust-lang/cargo/pull/12491)
+ [#12500](https://github.com/rust-lang/cargo/pull/12500)
## Cargo 1.72 (2023-08-24)
[64fb38c9...rust-1.72.0](https://github.com/rust-lang/cargo/compare/64fb38c9...rust-1.72.0)
@@ -57,10 +191,11 @@
### Changed
-- âť— Turned feature name validation check to a hard error. The warning was
- added in Rust 1.49. These extended characters aren't allowed on crates.io, so
- this should only impact users of other registries, or people who don't publish
- to a registry.
+- 🚨 [CVE-2023-40030](https://github.com/rust-lang/cargo/security/advisories/GHSA-wrrj-h57r-vx9p):
+ Malicious dependencies can inject arbitrary JavaScript into cargo-generated timing reports.
+ To mitigate this, feature name validation check is now turned into a hard error.
+ The warning was added in Rust 1.49. These extended characters aren't allowed on crates.io,
+ so this should only impact users of other registries, or people who don't publish to a registry.
[#12291](https://github.com/rust-lang/cargo/pull/12291)
- Cargo now warns when an edition 2021 package is in a virtual workspace and
`workspace.resolver` is not set. It is recommended to set the resolver
@@ -75,6 +210,9 @@
[#12231](https://github.com/rust-lang/cargo/pull/12231)
- Added a message when `rustup` override shorthand is put in a wrong position.
[#12226](https://github.com/rust-lang/cargo/pull/12226)
+- Respect scp-like URL as much as possible when fetching nested submodules.
+ [#12359](https://github.com/rust-lang/cargo/pull/12359)
+ [#12411](https://github.com/rust-lang/cargo/pull/12411)
### Fixed
@@ -184,6 +322,14 @@
- Show a better error when container tests fail.
[#12264](https://github.com/rust-lang/cargo/pull/12264)
+## Cargo 1.71.1 (2023-08-03)
+
+### Fixed
+
+- 🚨 [CVE-2023-38497](https://github.com/rust-lang/cargo/security/advisories/GHSA-j3xp-wfr4-hx87):
+ Cargo 1.71.1 or later respects umask when extracting crate archives. It also
+ purges the caches it tries to access if they were generated by older Cargo versions.
+
## Cargo 1.71 (2023-07-13)
[84b7041f...rust-1.71.0](https://github.com/rust-lang/cargo/compare/84b7041f...rust-1.71.0)
@@ -283,7 +429,7 @@
[#10877](https://github.com/rust-lang/cargo/pull/10877)
- SemVer: It is not a breaking change to make an unsafe function safe.
[#12116](https://github.com/rust-lang/cargo/pull/12116)
-- SemVer: changeing MSRV is generally a minor change.
+- SemVer: changing MSRV is generally a minor change.
[#12122](https://github.com/rust-lang/cargo/pull/12122)
- Clarify when and how to `cargo yank`.
[#11862](https://github.com/rust-lang/cargo/pull/11862)
@@ -582,9 +728,9 @@
- Clarified the difference between `CARGO_CRATE_NAME` and `CARGO_PKG_NAME`.
[#11576](https://github.com/rust-lang/cargo/pull/11576)
-- Added links to the Target section of the glossary for occurences of target triple.
+- Added links to the Target section of the glossary for occurrences of target triple.
[#11603](https://github.com/rust-lang/cargo/pull/11603)
-- Described how the current resolver sometimes duplicates depenencies.
+- Described how the current resolver sometimes duplicates dependencies.
[#11604](https://github.com/rust-lang/cargo/pull/11604)
- Added a note about verifying your email address on crates.io.
[#11620](https://github.com/rust-lang/cargo/pull/11620)
@@ -743,7 +889,7 @@
### Nightly only
-- Implemented a inital support of asymmetric token authentication for registries.
+- Implemented a initial support of asymmetric token authentication for registries.
([RFC 3231](https://github.com/rust-lang/rfcs/blob/master/text/3231-cargo-asymmetric-tokens.md))
([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#registry-auth))
[#10771](https://github.com/rust-lang/cargo/pull/10771)
@@ -859,7 +1005,7 @@
## Cargo 1.66.1 (2023-01-10)
### Fixed
-- [CVE-2022-46176](https://github.com/rust-lang/cargo/security/advisories/GHSA-r5w3-xm58-jv6j):
+- 🚨 [CVE-2022-46176](https://github.com/rust-lang/cargo/security/advisories/GHSA-r5w3-xm58-jv6j):
Added validation of SSH host keys for git URLs.
See [the docs](https://doc.rust-lang.org/cargo/appendix/git-authentication.html#ssh-known-hosts) for more information on how to configure the known host keys.
@@ -1085,11 +1231,11 @@
### Fixed
-- [CVE-2022-36113](https://github.com/rust-lang/cargo/security/advisories/GHSA-rfj2-q3h3-hm5j):
+- 🚨 [CVE-2022-36113](https://github.com/rust-lang/cargo/security/advisories/GHSA-rfj2-q3h3-hm5j):
Extracting malicious crates can corrupt arbitrary files.
[#11089](https://github.com/rust-lang/cargo/pull/11089)
[#11088](https://github.com/rust-lang/cargo/pull/11088)
-- [CVE-2022-36114](https://github.com/rust-lang/cargo/security/advisories/GHSA-2hvr-h6gw-qrxp):
+- 🚨 [CVE-2022-36114](https://github.com/rust-lang/cargo/security/advisories/GHSA-2hvr-h6gw-qrxp):
Extracting malicious crates can fill the file system.
[#11089](https://github.com/rust-lang/cargo/pull/11089)
[#11088](https://github.com/rust-lang/cargo/pull/11088)
diff --git a/src/tools/cargo/Cargo.lock b/src/tools/cargo/Cargo.lock
index 371504138..cc0cb9a88 100644
--- a/src/tools/cargo/Cargo.lock
+++ b/src/tools/cargo/Cargo.lock
@@ -9,27 +9,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
-name = "ahash"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
-dependencies = [
- "cfg-if",
- "getrandom",
- "once_cell",
- "version_check",
-]
-
-[[package]]
-name = "aho-corasick"
-version = "0.7.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
-dependencies = [
- "memchr",
-]
-
-[[package]]
name = "aho-corasick"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -46,24 +25,23 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
-version = "0.3.2"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
+checksum = "83d7b3983a025adeb201ef26a5564ebd1641ea9851f6282aee4940f745a3c07c"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
- "is-terminal",
"utf8parse",
]
[[package]]
name = "anstyle"
-version = "1.0.0"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
+checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
[[package]]
name = "anstyle-parse"
@@ -85,9 +63,9 @@ dependencies = [
[[package]]
name = "anstyle-wincon"
-version = "1.0.1"
+version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
+checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
dependencies = [
"anstyle",
"windows-sys",
@@ -95,9 +73,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.72"
+version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
+checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "arc-swap"
@@ -106,12 +84,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
[[package]]
-name = "arrayvec"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
-
-[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -125,9 +97,9 @@ checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
[[package]]
name = "base64"
-version = "0.21.2"
+version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
+checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53"
[[package]]
name = "base64ct"
@@ -193,13 +165,12 @@ dependencies = [
[[package]]
name = "bstr"
-version = "1.5.0"
+version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5"
+checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a"
dependencies = [
"memchr",
- "once_cell",
- "regex-automata",
+ "regex-automata 0.3.8",
"serde",
]
@@ -232,9 +203,15 @@ checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]]
name = "bytesize"
-version = "1.2.0"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38fcc2979eff34a4b84e1cf9a1e3da42a7d44b3b690a40cdcb23e3d556cfb2e5"
+checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc"
+
+[[package]]
+name = "byteyarn"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7534301c0ea17abb4db06d75efc7b4b0fa360fce8e175a4330d721c71c942ff"
[[package]]
name = "camino"
@@ -257,8 +234,10 @@ dependencies = [
[[package]]
name = "cargo"
-version = "0.74.0"
+version = "0.75.0"
dependencies = [
+ "anstream",
+ "anstyle",
"anyhow",
"base64",
"bytesize",
@@ -266,17 +245,17 @@ dependencies = [
"cargo-credential-libsecret",
"cargo-credential-macos-keychain",
"cargo-credential-wincred",
- "cargo-platform 0.1.4",
+ "cargo-platform 0.1.5",
"cargo-test-macro",
"cargo-test-support",
"cargo-util",
"clap",
+ "color-print",
"crates-io",
"curl",
"curl-sys",
"filetime",
"flate2",
- "fwdansi",
"git2",
"git2-curl",
"gix",
@@ -307,17 +286,16 @@ dependencies = [
"same-file",
"semver",
"serde",
+ "serde-untagged",
"serde-value",
"serde_ignored",
"serde_json",
"sha1",
"shell-escape",
"snapbox",
- "strip-ansi-escapes",
- "syn 2.0.28",
+ "syn 2.0.29",
"tar",
"tempfile",
- "termcolor",
"time",
"toml",
"toml_edit",
@@ -333,7 +311,7 @@ dependencies = [
[[package]]
name = "cargo-credential"
-version = "0.3.0"
+version = "0.4.0"
dependencies = [
"anyhow",
"libc",
@@ -347,7 +325,7 @@ dependencies = [
[[package]]
name = "cargo-credential-1password"
-version = "0.3.0"
+version = "0.4.0"
dependencies = [
"cargo-credential",
"serde",
@@ -356,7 +334,7 @@ dependencies = [
[[package]]
name = "cargo-credential-libsecret"
-version = "0.3.1"
+version = "0.3.2"
dependencies = [
"anyhow",
"cargo-credential",
@@ -365,7 +343,7 @@ dependencies = [
[[package]]
name = "cargo-credential-macos-keychain"
-version = "0.3.0"
+version = "0.3.1"
dependencies = [
"cargo-credential",
"security-framework",
@@ -373,7 +351,7 @@ dependencies = [
[[package]]
name = "cargo-credential-wincred"
-version = "0.3.0"
+version = "0.3.1"
dependencies = [
"cargo-credential",
"windows-sys",
@@ -390,7 +368,7 @@ dependencies = [
[[package]]
name = "cargo-platform"
-version = "0.1.4"
+version = "0.1.5"
dependencies = [
"serde",
]
@@ -403,6 +381,8 @@ version = "0.1.0"
name = "cargo-test-support"
version = "0.1.0"
dependencies = [
+ "anstream",
+ "anstyle",
"anyhow",
"cargo-test-macro",
"cargo-util",
@@ -412,13 +392,11 @@ dependencies = [
"git2",
"glob",
"itertools",
- "lazy_static",
"pasetors",
"serde",
"serde_json",
"snapbox",
"tar",
- "termcolor",
"time",
"toml",
"url",
@@ -427,7 +405,7 @@ dependencies = [
[[package]]
name = "cargo-util"
-version = "0.2.6"
+version = "0.2.7"
dependencies = [
"anyhow",
"core-foundation",
@@ -447,15 +425,16 @@ dependencies = [
[[package]]
name = "cargo_metadata"
-version = "0.14.2"
+version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
+checksum = "e7daec1a2a2129eeba1644b220b4647ec537b0b5d4bfd6876fcc5a540056b592"
dependencies = [
"camino",
"cargo-platform 0.1.2",
"semver",
"serde",
"serde_json",
+ "thiserror",
]
[[package]]
@@ -508,18 +487,18 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.3.19"
+version = "4.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d"
+checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
-version = "4.3.19"
+version = "4.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1"
+checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45"
dependencies = [
"anstream",
"anstyle",
@@ -541,6 +520,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807"
[[package]]
+name = "color-print"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2a5e6504ed8648554968650feecea00557a3476bc040d0ffc33080e66b646d0"
+dependencies = [
+ "color-print-proc-macro",
+]
+
+[[package]]
+name = "color-print-proc-macro"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d51beaa537d73d2d1ff34ee70bc095f170420ab2ec5d687ecd3ec2b0d092514b"
+dependencies = [
+ "nom",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -588,7 +588,7 @@ dependencies = [
[[package]]
name = "crates-io"
-version = "0.38.0"
+version = "0.39.0"
dependencies = [
"curl",
"percent-encoding",
@@ -731,9 +731,9 @@ dependencies = [
[[package]]
name = "curl-sys"
-version = "0.4.65+curl-8.2.1"
+version = "0.4.68+curl-8.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "961ba061c9ef2fe34bbd12b807152d96f0badd2bebe7b90ce6c8c8b7572a0986"
+checksum = "b4a0d18d88360e374b16b2273c832b5e57258ffc1d4aa4f96b108e0738d5752f"
dependencies = [
"cc",
"libc",
@@ -742,7 +742,7 @@ dependencies = [
"openssl-sys",
"pkg-config",
"vcpkg",
- "winapi",
+ "windows-sys",
]
[[package]]
@@ -757,6 +757,15 @@ dependencies = [
]
[[package]]
+name = "deranged"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -831,12 +840,30 @@ dependencies = [
]
[[package]]
+name = "encoding_rs"
+version = "0.8.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
+name = "erased-serde"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "errno"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -870,12 +897,12 @@ dependencies = [
]
[[package]]
-name = "fastrand"
-version = "1.9.0"
+name = "faster-hex"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+checksum = "239f7bfb930f820ab16a9cd95afc26f88264cf6905c960b340a615384aa3338a"
dependencies = [
- "instant",
+ "serde",
]
[[package]]
@@ -902,21 +929,21 @@ checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
[[package]]
name = "filetime"
-version = "0.2.21"
+version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
+checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall 0.2.16",
+ "redox_syscall",
"windows-sys",
]
[[package]]
name = "flate2"
-version = "1.0.26"
+version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
+checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
dependencies = [
"crc32fast",
"libz-sys",
@@ -954,16 +981,6 @@ dependencies = [
]
[[package]]
-name = "fwdansi"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08c1f5787fe85505d1f7777268db5103d80a7a374d2316a7ce262e57baf8f208"
-dependencies = [
- "memchr",
- "termcolor",
-]
-
-[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -989,11 +1006,11 @@ dependencies = [
[[package]]
name = "git2"
-version = "0.17.2"
+version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b989d6a7ca95a362cf2cfc5ad688b3a467be1f87e480b8dad07fee8c79b0044"
+checksum = "12ef350ba88a33b4d524b1d1c79096c9ade5ef8c59395df0e60d1e1889414c0e"
dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.3.3",
"libc",
"libgit2-sys",
"log",
@@ -1004,9 +1021,9 @@ dependencies = [
[[package]]
name = "git2-curl"
-version = "0.18.0"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8f8b7432b72928cff76f69e59ed5327f94a52763731e71274960dee72fe5f8c"
+checksum = "78e26b61608c573ffd26fc79061a823aa5147449a1afe1f61679a21e2031f7c3"
dependencies = [
"curl",
"git2",
@@ -1016,9 +1033,9 @@ dependencies = [
[[package]]
name = "gix"
-version = "0.45.1"
+version = "0.54.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf2a03ec66ee24d1b2bae3ab718f8d14f141613810cb7ff6756f7db667f1cd82"
+checksum = "ad6d32e74454459690d57d18ea4ebec1629936e6b130b51d12cb4a81630ac953"
dependencies = [
"gix-actor",
"gix-attributes",
@@ -1029,6 +1046,7 @@ dependencies = [
"gix-diff",
"gix-discover",
"gix-features",
+ "gix-filter",
"gix-fs",
"gix-glob",
"gix-hash",
@@ -1036,29 +1054,32 @@ dependencies = [
"gix-ignore",
"gix-index",
"gix-lock",
- "gix-mailmap",
+ "gix-macros",
"gix-negotiate",
"gix-object",
"gix-odb",
"gix-pack",
"gix-path",
+ "gix-pathspec",
"gix-prompt",
"gix-protocol",
"gix-ref",
"gix-refspec",
"gix-revision",
+ "gix-revwalk",
"gix-sec",
+ "gix-submodule",
"gix-tempfile",
+ "gix-trace",
"gix-transport",
"gix-traverse",
"gix-url",
"gix-utils",
"gix-validate",
"gix-worktree",
- "log",
"once_cell",
+ "parking_lot",
"prodash",
- "signal-hook",
"smallvec",
"thiserror",
"unicode-normalization",
@@ -1066,30 +1087,30 @@ dependencies = [
[[package]]
name = "gix-actor"
-version = "0.21.0"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fe73f9f6be1afbf1bd5be919a9636fa560e2f14d42262a934423ed6760cd838"
+checksum = "08c60e982c5290897122d4e2622447f014a2dadd5a18cb73d50bb91b31645e27"
dependencies = [
"bstr",
"btoi",
"gix-date",
"itoa 1.0.6",
- "nom",
"thiserror",
+ "winnow",
]
[[package]]
name = "gix-attributes"
-version = "0.13.1"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78b79590ac382f80d87e06416f5fcac6fee5d83dcb152a00ed0bdbaa988acc31"
+checksum = "2451665e70709ba4753b623ef97511ee98c4a73816b2c5b5df25678d607ed820"
dependencies = [
"bstr",
+ "byteyarn",
"gix-glob",
"gix-path",
"gix-quote",
- "kstring",
- "log",
+ "gix-trace",
"smallvec",
"thiserror",
"unicode-bom",
@@ -1097,36 +1118,36 @@ dependencies = [
[[package]]
name = "gix-bitmap"
-version = "0.2.4"
+version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc02feb20ad313d52a450852f2005c2205d24f851e74d82b7807cbe12c371667"
+checksum = "0ccab4bc576844ddb51b78d81b4a42d73e6229660fa614dfc3d3999c874d1959"
dependencies = [
"thiserror",
]
[[package]]
name = "gix-chunk"
-version = "0.4.2"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7acf3bc6c4b91e8fb260086daf5e105ea3a6d913f5fd3318137f7e309d6e540"
+checksum = "5b42ea64420f7994000130328f3c7a2038f639120518870436d31b8bde704493"
dependencies = [
"thiserror",
]
[[package]]
name = "gix-command"
-version = "0.2.5"
+version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f6141b70cfb21255223e42f3379855037cbbe8673b58dd8318d2f09b516fad1"
+checksum = "0f28f654184b5f725c5737c7e4f466cbd8f0102ac352d5257eeab19647ee4256"
dependencies = [
"bstr",
]
[[package]]
name = "gix-commitgraph"
-version = "0.16.0"
+version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8490ae1b3d55c47e6a71d247c082304a2f79f8d0332c1a2f5693d42a2021a09"
+checksum = "e75a975ee22cf0a002bfe9b5d5cb3d2a88e263a8a178cd7509133cff10f4df8a"
dependencies = [
"bstr",
"gix-chunk",
@@ -1138,9 +1159,9 @@ dependencies = [
[[package]]
name = "gix-config"
-version = "0.23.0"
+version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51f310120ae1ba8f0ca52fb22876ce9bad5b15c8ffb3eb7302e4b64a3b9f681c"
+checksum = "c171514b40487d3f677ae37efc0f45ac980e3169f23c27eb30a70b47fdf88ab5"
dependencies = [
"bstr",
"gix-config-value",
@@ -1149,20 +1170,19 @@ dependencies = [
"gix-path",
"gix-ref",
"gix-sec",
- "log",
"memchr",
- "nom",
"once_cell",
"smallvec",
"thiserror",
"unicode-bom",
+ "winnow",
]
[[package]]
name = "gix-config-value"
-version = "0.12.1"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f216df1c33e6e1555923eff0096858a879e8aaadd35b5d788641e4e8064c892"
+checksum = "ea7505b97f4d8e7933e29735a568ba2f86d8de466669d9f0e8321384f9972f47"
dependencies = [
"bitflags 2.3.3",
"bstr",
@@ -1173,9 +1193,9 @@ dependencies = [
[[package]]
name = "gix-credentials"
-version = "0.15.0"
+version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6f89fea8acd28f5ef8fa5042146f1637afd4d834bc8f13439d8fd1e5aca0d65"
+checksum = "46900b884cc5af6a6c141ee741607c0c651a4e1d33614b8d888a1ba81cc0bc8a"
dependencies = [
"bstr",
"gix-command",
@@ -1189,9 +1209,9 @@ dependencies = [
[[package]]
name = "gix-date"
-version = "0.5.1"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc164145670e9130a60a21670d9b6f0f4f8de04e5dd256c51fa5a0340c625902"
+checksum = "fc7df669639582dc7c02737642f76890b03b5544e141caba68a7d6b4eb551e0d"
dependencies = [
"bstr",
"itoa 1.0.6",
@@ -1201,21 +1221,20 @@ dependencies = [
[[package]]
name = "gix-diff"
-version = "0.30.1"
+version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9029ad0083cc286a4bd2f5b3bf66bb66398abc26f2731a2824cd5edfc41a0e33"
+checksum = "788ddb152c388206e81f36bcbb574e7ed7827c27d8fa62227b34edc333d8928c"
dependencies = [
"gix-hash",
"gix-object",
- "imara-diff",
"thiserror",
]
[[package]]
name = "gix-discover"
-version = "0.19.0"
+version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aba9c6c0d1f2b2efe65581de73de4305004612d49c83773e783202a7ef204f46"
+checksum = "69507643d75a0ea9a402fcf73ced517d2b95cc95385904ac09d03e0b952fde33"
dependencies = [
"bstr",
"dunce",
@@ -1228,15 +1247,16 @@ dependencies = [
[[package]]
name = "gix-features"
-version = "0.30.0"
+version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a8c493409bf6060d408eec9bbdd1b12ea351266b50012e2a522f75dfc7b8314"
+checksum = "9b9ff423ae4983f762659040d13dd7a5defbd54b6a04ac3cc7347741cec828cd"
dependencies = [
"bytes",
"crc32fast",
"crossbeam-channel",
"flate2",
"gix-hash",
+ "gix-trace",
"libc",
"once_cell",
"parking_lot",
@@ -1247,19 +1267,39 @@ dependencies = [
]
[[package]]
+name = "gix-filter"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1be40d28cd41445bb6cd52c4d847d915900e5466f7433eaee6a9e0a3d1d88b08"
+dependencies = [
+ "bstr",
+ "encoding_rs",
+ "gix-attributes",
+ "gix-command",
+ "gix-hash",
+ "gix-object",
+ "gix-packetline-blocking",
+ "gix-path",
+ "gix-quote",
+ "gix-trace",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
name = "gix-fs"
-version = "0.2.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30da8997008adb87f94e15beb7ee229f8a48e97af585a584bfee4a5a1880aab5"
+checksum = "09815faba62fe9b32d918b75a554686c98e43f7d48c43a80df58eb718e5c6635"
dependencies = [
"gix-features",
]
[[package]]
name = "gix-glob"
-version = "0.8.0"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd0ade1e80ab1f079703d1824e1daf73009096386aa7fd2f0477f6e4ac0a558e"
+checksum = "a9d76e85f11251dcf751d2c5e918a14f562db5be6f727fd24775245653e9b19d"
dependencies = [
"bitflags 2.3.3",
"bstr",
@@ -1269,30 +1309,30 @@ dependencies = [
[[package]]
name = "gix-hash"
-version = "0.11.3"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0dd58cdbe7ffa4032fc111864c80d5f8cecd9a2c9736c97ae7e5be834188272"
+checksum = "2ccf425543779cddaa4a7c62aba3fa9d90ea135b160be0a72dd93c063121ad4a"
dependencies = [
- "hex",
+ "faster-hex",
"thiserror",
]
[[package]]
name = "gix-hashtable"
-version = "0.2.3"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e133bc56d938eaec1c675af7c681a51de9662b0ada779f45607b967a10da77a"
+checksum = "409268480841ad008e81c17ca5a293393fbf9f2b6c2f85b8ab9de1f0c5176a16"
dependencies = [
"gix-hash",
- "hashbrown 0.14.0",
+ "hashbrown",
"parking_lot",
]
[[package]]
name = "gix-ignore"
-version = "0.3.0"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc6f7f101a0ccce808dbf7008ba131dede94e20257e7bde7a44cbb2f8c775625"
+checksum = "b048f443a1f6b02da4205c34d2e287e3fd45d75e8e2f06cfb216630ea9bff5e3"
dependencies = [
"bstr",
"gix-glob",
@@ -1302,9 +1342,9 @@ dependencies = [
[[package]]
name = "gix-index"
-version = "0.17.0"
+version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "616ba958fabfb11263fa042c35690d48a6c7be4e9277e2c7e24ff263b3fe7b82"
+checksum = "f54d63a9d13c13088f41f5a3accbec284e492ac8f4f707fcc307c139622e17b7"
dependencies = [
"bitflags 2.3.3",
"bstr",
@@ -1312,6 +1352,7 @@ dependencies = [
"filetime",
"gix-bitmap",
"gix-features",
+ "gix-fs",
"gix-hash",
"gix-lock",
"gix-object",
@@ -1324,9 +1365,9 @@ dependencies = [
[[package]]
name = "gix-lock"
-version = "6.0.0"
+version = "10.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ec5d5e6f07316d3553aa7425e3ecd935ec29882556021fe1696297a448af8d2"
+checksum = "47fc96fa8b6b6d33555021907c81eb3b27635daecf6e630630bdad44f8feaa95"
dependencies = [
"gix-tempfile",
"gix-utils",
@@ -1334,57 +1375,59 @@ dependencies = [
]
[[package]]
-name = "gix-mailmap"
-version = "0.13.0"
+name = "gix-macros"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4653701922c920e009f1bc4309feaff14882ade017770788f9a150928da3fa6a"
+checksum = "9d8acb5ee668d55f0f2d19a320a3f9ef67a6999ad483e11135abcc2464ed18b6"
dependencies = [
- "bstr",
- "gix-actor",
- "thiserror",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.29",
]
[[package]]
name = "gix-negotiate"
-version = "0.2.1"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "945c3ef1e912e44a5f405fc9e924edf42000566a1b257ed52cb1293300f6f08c"
+checksum = "6f1697bf9911c6d1b8d709b9e6ef718cb5ea5821a1b7991520125a8134448004"
dependencies = [
"bitflags 2.3.3",
"gix-commitgraph",
+ "gix-date",
"gix-hash",
"gix-object",
- "gix-revision",
+ "gix-revwalk",
"smallvec",
"thiserror",
]
[[package]]
name = "gix-object"
-version = "0.30.0"
+version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8926c8f51c44dec3e709cb5dbc93deb9e8d4064c43c9efc54c158dcdfe8446c7"
+checksum = "1e7e19616c67967374137bae83e950e9b518a9ea8a605069bd6716ada357fd6f"
dependencies = [
"bstr",
"btoi",
"gix-actor",
+ "gix-date",
"gix-features",
"gix-hash",
"gix-validate",
- "hex",
"itoa 1.0.6",
- "nom",
"smallvec",
"thiserror",
+ "winnow",
]
[[package]]
name = "gix-odb"
-version = "0.46.0"
+version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b234d806278eeac2f907c8b5a105c4ba537230c1a9d9236d822bf0db291f8f3"
+checksum = "8d6a392c6ba3a2f133cdc63120e9bc7aec81eef763db372c817de31febfe64bf"
dependencies = [
"arc-swap",
+ "gix-date",
"gix-features",
"gix-hash",
"gix-object",
@@ -1398,20 +1441,18 @@ dependencies = [
[[package]]
name = "gix-pack"
-version = "0.36.0"
+version = "0.43.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d2a14cb3156037eedb17d6cb7209b7180522b8949b21fd0fe3184c0a1d0af88"
+checksum = "7536203a45b31e1bc5694bbf90ba8da1b736c77040dd6a520db369f371eb1ab3"
dependencies = [
"clru",
"gix-chunk",
- "gix-diff",
"gix-features",
"gix-hash",
"gix-hashtable",
"gix-object",
"gix-path",
"gix-tempfile",
- "gix-traverse",
"memmap2",
"parking_lot",
"smallvec",
@@ -1420,62 +1461,90 @@ dependencies = [
[[package]]
name = "gix-packetline"
-version = "0.16.2"
+version = "0.16.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74414f89a6b72fa1a530ce8e646faf1a05499c3f4a5c15441d17ae8c978578eb"
+checksum = "d6df0b75361353e7c0a6d72d49617a37379a7a22cba4569ae33a7720a4c8755a"
dependencies = [
"bstr",
- "hex",
+ "faster-hex",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-packetline-blocking"
+version = "0.16.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d8395f7501c84d6a1fe902035fdfd8cd86d89e2dd6be0200ec1a72fd3c92d39"
+dependencies = [
+ "bstr",
+ "faster-hex",
"thiserror",
]
[[package]]
name = "gix-path"
-version = "0.8.1"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1226f2e50adeb4d76c754c1856c06f13a24cad1624801653fbf09b869e5b808"
+checksum = "6a1d370115171e3ae03c5c6d4f7d096f2981a40ddccb98dfd704c773530ba73b"
dependencies = [
"bstr",
+ "gix-trace",
"home 0.5.5",
"once_cell",
"thiserror",
]
[[package]]
+name = "gix-pathspec"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3e26c9b47c51be73f98d38c84494bd5fb99334c5d6fda14ef5d036d50a9e5fd"
+dependencies = [
+ "bitflags 2.3.3",
+ "bstr",
+ "gix-attributes",
+ "gix-config-value",
+ "gix-glob",
+ "gix-path",
+ "thiserror",
+]
+
+[[package]]
name = "gix-prompt"
-version = "0.5.1"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e15fe57fa48572b7d3bf465d6a2a0351cd3c55cba74fd5f0b9c23689f9c1a31e"
+checksum = "5c9a913769516f5e9d937afac206fb76428e3d7238e538845842887fda584678"
dependencies = [
"gix-command",
"gix-config-value",
"parking_lot",
- "rustix 0.37.20",
+ "rustix",
"thiserror",
]
[[package]]
name = "gix-protocol"
-version = "0.33.2"
+version = "0.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92a17058b45c461f0847528c5fb6ee6e76115e026979eb2d2202f98ee94f6c24"
+checksum = "cc7b700dc20cc9be8a5130a1fd7e10c34117ffa7068431c8c24d963f0a2e0c9b"
dependencies = [
"bstr",
"btoi",
"gix-credentials",
+ "gix-date",
"gix-features",
"gix-hash",
"gix-transport",
"maybe-async",
- "nom",
"thiserror",
+ "winnow",
]
[[package]]
name = "gix-quote"
-version = "0.4.4"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29d59489bff95b06dcdabe763b7266d3dc0a628cac1ac1caf65a7ca0a43eeae0"
+checksum = "475c86a97dd0127ba4465fbb239abac9ea10e68301470c9791a6dd5351cdc905"
dependencies = [
"bstr",
"btoi",
@@ -1484,11 +1553,12 @@ dependencies = [
[[package]]
name = "gix-ref"
-version = "0.30.0"
+version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebdd999256f4ce8a5eefa89999879c159c263f3493a951d62aa5ce42c0397e1c"
+checksum = "22e6b749660b613641769edc1954132eb8071a13c32224891686091bef078de4"
dependencies = [
"gix-actor",
+ "gix-date",
"gix-features",
"gix-fs",
"gix-hash",
@@ -1498,15 +1568,15 @@ dependencies = [
"gix-tempfile",
"gix-validate",
"memmap2",
- "nom",
"thiserror",
+ "winnow",
]
[[package]]
name = "gix-refspec"
-version = "0.11.0"
+version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72bfd622abc86dd8ad1ec51b9eb77b4f1a766b94e3a1b87cf4a022c5b5570cf4"
+checksum = "0895cb7b1e70f3c3bd4550c329e9f5caf2975f97fcd4238e05754e72208ef61e"
dependencies = [
"bstr",
"gix-hash",
@@ -1518,9 +1588,9 @@ dependencies = [
[[package]]
name = "gix-revision"
-version = "0.15.2"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5044f56cd7a487ce9b034cbe0252ae0b6b47ff56ca3dabd79bc30214d0932cd7"
+checksum = "c8c4b15cf2ab7a35f5bcb3ef146187c8d36df0177e171ca061913cbaaa890e89"
dependencies = [
"bstr",
"gix-date",
@@ -1528,16 +1598,18 @@ dependencies = [
"gix-hashtable",
"gix-object",
"gix-revwalk",
+ "gix-trace",
"thiserror",
]
[[package]]
name = "gix-revwalk"
-version = "0.1.0"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc2623ba8747914f151f5e12b65adac576ab459dbed5f50a36c7a3e9cbf2d3ca"
+checksum = "e9870c6b1032f2084567710c3b2106ac603377f8d25766b8a6b7c33e6e3ca279"
dependencies = [
"gix-commitgraph",
+ "gix-date",
"gix-hash",
"gix-hashtable",
"gix-object",
@@ -1547,9 +1619,9 @@ dependencies = [
[[package]]
name = "gix-sec"
-version = "0.8.1"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2b7b38b766eb95dcc5350a9c450030b69892c0902fa35f4a6d0809273bd9dae"
+checksum = "92b9542ac025a8c02ed5d17b3fc031a111a384e859d0be3532ec4d58c40a0f28"
dependencies = [
"bitflags 2.3.3",
"gix-path",
@@ -1558,25 +1630,44 @@ dependencies = [
]
[[package]]
+name = "gix-submodule"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0150e82e9282d3f2ab2dd57a22f9f6c3447b9d9856e5321ac92d38e3e0e2b7"
+dependencies = [
+ "bstr",
+ "gix-config",
+ "gix-path",
+ "gix-pathspec",
+ "gix-refspec",
+ "gix-url",
+ "thiserror",
+]
+
+[[package]]
name = "gix-tempfile"
-version = "6.0.0"
+version = "10.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3785cb010e9dc5c446dfbf02bc1119fc17d3a48a27c029efcb3a3c32953eb10"
+checksum = "5ae0978f3e11dc57290ee75ac2477c815bca1ce2fa7ed5dc5f16db067410ac4d"
dependencies = [
"gix-fs",
"libc",
"once_cell",
"parking_lot",
- "signal-hook",
- "signal-hook-registry",
"tempfile",
]
[[package]]
+name = "gix-trace"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96b6d623a1152c3facb79067d6e2ecdae48130030cf27d6eb21109f13bd7b836"
+
+[[package]]
name = "gix-transport"
-version = "0.32.0"
+version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64a39ffed9a9078ed700605e064b15d7c6ae50aa65e7faa36ca6919e8081df15"
+checksum = "b9ec726e6a245e68ace59a34126a1d679de60360676612985e70b0d3b102fb4e"
dependencies = [
"base64",
"bstr",
@@ -1593,21 +1684,25 @@ dependencies = [
[[package]]
name = "gix-traverse"
-version = "0.26.0"
+version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0842e984cb4bf26339dc559f3a1b8bf8cdb83547799b2b096822a59f87f33d9"
+checksum = "22ef04ab3643acba289b5cedd25d6f53c0430770b1d689d1d654511e6fb81ba0"
dependencies = [
+ "gix-commitgraph",
+ "gix-date",
"gix-hash",
"gix-hashtable",
"gix-object",
+ "gix-revwalk",
+ "smallvec",
"thiserror",
]
[[package]]
name = "gix-url"
-version = "0.19.0"
+version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1663df25ac42047a2547618d2a6979a26f478073f6306997429235d2cd4c863"
+checksum = "6125ecf46e8c68bf7202da6cad239831daebf0247ffbab30210d72f3856e420f"
dependencies = [
"bstr",
"gix-features",
@@ -1619,18 +1714,18 @@ dependencies = [
[[package]]
name = "gix-utils"
-version = "0.1.2"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbcfcb150c7ef553d76988467d223254045bdcad0dc6724890f32fbe96415da5"
+checksum = "b85d89dc728613e26e0ed952a19583744e7f5240fcd4aa30d6c824ffd8b52f0f"
dependencies = [
- "fastrand 1.9.0",
+ "fastrand",
]
[[package]]
name = "gix-validate"
-version = "0.7.5"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57ea5845b506c7728b9d89f4227cc369a5fc5a1d5b26c3add0f0d323413a3a60"
+checksum = "e05cab2b03a45b866156e052aa38619f4ece4adcb2f79978bfc249bc3b21b8c5"
dependencies = [
"bstr",
"thiserror",
@@ -1638,12 +1733,11 @@ dependencies = [
[[package]]
name = "gix-worktree"
-version = "0.18.0"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d388ad962e8854402734a7387af8790f6bdbc8d05349052dab16ca4a0def50f6"
+checksum = "9f5e32972801bd82d56609e6fc84efc358fa1f11f25c5e83b7807ee2280f14fe"
dependencies = [
"bstr",
- "filetime",
"gix-attributes",
"gix-features",
"gix-fs",
@@ -1653,8 +1747,6 @@ dependencies = [
"gix-index",
"gix-object",
"gix-path",
- "io-close",
- "thiserror",
]
[[package]]
@@ -1665,11 +1757,11 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "globset"
-version = "0.4.10"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
+checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d"
dependencies = [
- "aho-corasick 0.7.20",
+ "aho-corasick",
"bstr",
"fnv",
"log",
@@ -1710,12 +1802,6 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-
-[[package]]
-name = "hashbrown"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
@@ -1832,64 +1918,23 @@ dependencies = [
]
[[package]]
-name = "imara-diff"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e98c1d0ad70fc91b8b9654b1f33db55e59579d3b3de2bffdced0fdb810570cb8"
-dependencies = [
- "ahash",
- "hashbrown 0.12.3",
-]
-
-[[package]]
name = "indexmap"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
dependencies = [
"equivalent",
- "hashbrown 0.14.0",
-]
-
-[[package]]
-name = "instant"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "io-close"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc"
-dependencies = [
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "io-lifetimes"
-version = "1.0.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
-dependencies = [
- "hermit-abi 0.3.2",
- "libc",
- "windows-sys",
+ "hashbrown",
]
[[package]]
name = "is-terminal"
-version = "0.4.7"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
+checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [
"hermit-abi 0.3.2",
- "io-lifetimes",
- "rustix 0.37.20",
+ "rustix",
"windows-sys",
]
@@ -1933,15 +1978,6 @@ dependencies = [
]
[[package]]
-name = "kstring"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747"
-dependencies = [
- "static_assertions",
-]
-
-[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1961,15 +1997,15 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "libc"
-version = "0.2.147"
+version = "0.2.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
[[package]]
name = "libgit2-sys"
-version = "0.15.2+1.6.4"
+version = "0.16.1+1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a80df2e11fb4a61f4ba2ab42dbe7f74468da143f1a75c74e11dee7c813f694fa"
+checksum = "f2a2bb3680b094add03bb3732ec520ece34da31a8cd2d633d1389d0f0fb60d0c"
dependencies = [
"cc",
"libc",
@@ -2033,12 +2069,6 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
-
-[[package]]
-name = "linux-raw-sys"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
@@ -2065,7 +2095,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
- "regex-automata",
+ "regex-automata 0.1.10",
]
[[package]]
@@ -2094,15 +2124,15 @@ dependencies = [
[[package]]
name = "memchr"
-version = "2.5.0"
+version = "2.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e"
[[package]]
name = "memmap2"
-version = "0.5.10"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327"
+checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6"
dependencies = [
"libc",
]
@@ -2229,11 +2259,11 @@ dependencies = [
[[package]]
name = "openssl"
-version = "0.10.55"
+version = "0.10.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d"
+checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.3.3",
"cfg-if",
"foreign-types",
"libc",
@@ -2250,7 +2280,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.29",
]
[[package]]
@@ -2270,9 +2300,9 @@ dependencies = [
[[package]]
name = "openssl-sys"
-version = "0.9.90"
+version = "0.9.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6"
+checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b"
dependencies = [
"cc",
"libc",
@@ -2348,7 +2378,7 @@ checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall 0.3.5",
+ "redox_syscall",
"smallvec",
"windows-targets",
]
@@ -2445,7 +2475,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.29",
]
[[package]]
@@ -2545,9 +2575,9 @@ dependencies = [
[[package]]
name = "prodash"
-version = "25.0.0"
+version = "26.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3236ce1618b6da4c7b618e0143c4d5b5dc190f75f81c49f248221382f7e9e9ae"
+checksum = "794b5bf8e2d19b53dcdcec3e4bba628e20f5b6062503ba89281fa7037dd7bbcf"
dependencies = [
"parking_lot",
]
@@ -2676,15 +2706,6 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
-dependencies = [
- "bitflags 1.3.2",
-]
-
-[[package]]
-name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
@@ -2698,7 +2719,7 @@ version = "1.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
dependencies = [
- "aho-corasick 1.0.2",
+ "aho-corasick",
"memchr",
"regex-syntax 0.7.2",
]
@@ -2713,6 +2734,12 @@ dependencies = [
]
[[package]]
+name = "regex-automata"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
+
+[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2730,7 +2757,6 @@ version = "0.0.0"
dependencies = [
"cargo",
"cargo-util",
- "lazy_static",
"proptest",
"varisat",
]
@@ -2765,20 +2791,6 @@ dependencies = [
[[package]]
name = "rustix"
-version = "0.37.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0"
-dependencies = [
- "bitflags 1.3.2",
- "errno",
- "io-lifetimes",
- "libc",
- "linux-raw-sys 0.3.8",
- "windows-sys",
-]
-
-[[package]]
-name = "rustix"
version = "0.38.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ee020b1716f0a80e2ace9b03441a749e402e86712f15f16fe8a8f75afac732f"
@@ -2786,7 +2798,7 @@ dependencies = [
"bitflags 2.3.3",
"errno",
"libc",
- "linux-raw-sys 0.4.5",
+ "linux-raw-sys",
"windows-sys",
]
@@ -2887,14 +2899,24 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.171"
+version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9"
+checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
dependencies = [
"serde_derive",
]
[[package]]
+name = "serde-untagged"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ba3ac59c62f51b75a6bfad8840b2ede4a81ff5cc23c200221ef479ae75a4aa3"
+dependencies = [
+ "erased-serde",
+ "serde",
+]
+
+[[package]]
name = "serde-value"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2906,13 +2928,13 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.171"
+version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682"
+checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.29",
]
[[package]]
@@ -2926,9 +2948,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.104"
+version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
+checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
dependencies = [
"itoa 1.0.6",
"ryu",
@@ -2988,25 +3010,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
[[package]]
-name = "signal-hook"
-version = "0.3.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9"
-dependencies = [
- "libc",
- "signal-hook-registry",
-]
-
-[[package]]
-name = "signal-hook-registry"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
-dependencies = [
- "libc",
-]
-
-[[package]]
name = "signature"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3040,9 +3043,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "snapbox"
-version = "0.4.11"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6bccd62078347f89a914e3004d94582e13824d4e3d8a816317862884c423835"
+checksum = "7b439536a42c43be148b610c7f7f968fb79a457254910a9cb20900da73cd3271"
dependencies = [
"anstream",
"anstyle",
@@ -3059,9 +3062,9 @@ dependencies = [
[[package]]
name = "snapbox-macros"
-version = "0.3.4"
+version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eaaf09df9f0eeae82be96290918520214530e738a7fe5a351b0f24cf77c0ca31"
+checksum = "ed1559baff8a696add3322b9be3e940d433e7bb4e38d79017205fd37ff28b28e"
dependencies = [
"anstream",
]
@@ -3087,21 +3090,6 @@ dependencies = [
]
[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
-name = "strip-ansi-escapes"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "011cbb39cf7c1f62871aea3cc46e5817b0937b49e9447370c93cacbe93a766d8"
-dependencies = [
- "vte",
-]
-
-[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3126,9 +3114,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.28"
+version = "2.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
dependencies = [
"proc-macro2",
"quote",
@@ -3149,9 +3137,9 @@ dependencies = [
[[package]]
name = "tar"
-version = "0.4.39"
+version = "0.4.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec96d2ffad078296368d46ff1cb309be1c23c513b4ab0e22a45de0185275ac96"
+checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
dependencies = [
"filetime",
"libc",
@@ -3159,54 +3147,45 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.7.0"
+version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998"
+checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
dependencies = [
"cfg-if",
- "fastrand 2.0.0",
- "redox_syscall 0.3.5",
- "rustix 0.38.6",
+ "fastrand",
+ "redox_syscall",
+ "rustix",
"windows-sys",
]
[[package]]
-name = "termcolor"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
name = "terminal_size"
-version = "0.2.6"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237"
+checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
dependencies = [
- "rustix 0.37.20",
+ "rustix",
"windows-sys",
]
[[package]]
name = "thiserror"
-version = "1.0.44"
+version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
+checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.44"
+version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
+checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.29",
]
[[package]]
@@ -3221,10 +3200,11 @@ dependencies = [
[[package]]
name = "time"
-version = "0.3.22"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
+checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe"
dependencies = [
+ "deranged",
"itoa 1.0.6",
"libc",
"num_threads",
@@ -3235,15 +3215,15 @@ dependencies = [
[[package]]
name = "time-core"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
+checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
-version = "0.2.9"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
+checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
dependencies = [
"time-core",
]
@@ -3327,7 +3307,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.29",
]
[[package]]
@@ -3389,9 +3369,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
[[package]]
name = "unicase"
-version = "2.6.0"
+version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
@@ -3437,9 +3417,9 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "url"
-version = "2.4.0"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
+checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
dependencies = [
"form_urlencoded",
"idna",
@@ -3558,27 +3538,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
-name = "vte"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983"
-dependencies = [
- "arrayvec",
- "utf8parse",
- "vte_generate_state_changes",
-]
-
-[[package]]
-name = "vte_generate_state_changes"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff"
-dependencies = [
- "proc-macro2",
- "quote",
-]
-
-[[package]]
name = "wait-timeout"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3624,7 +3583,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.29",
"wasm-bindgen-shared",
]
@@ -3646,7 +3605,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.29",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -3775,9 +3734,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winnow"
-version = "0.5.0"
+version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7"
+checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"
dependencies = [
"memchr",
]
diff --git a/src/tools/cargo/Cargo.toml b/src/tools/cargo/Cargo.toml
index 0e189a6d4..440304416 100644
--- a/src/tools/cargo/Cargo.toml
+++ b/src/tools/cargo/Cargo.toml
@@ -11,15 +11,18 @@ exclude = [
]
[workspace.package]
+rust-version = "1.72.0"
edition = "2021"
license = "MIT OR Apache-2.0"
[workspace.dependencies]
-anyhow = "1.0.72"
-base64 = "0.21.2"
-bytesize = "1.2"
+anstream = "0.6.3"
+anstyle = "1.0.4"
+anyhow = "1.0.75"
+base64 = "0.21.3"
+bytesize = "1.3"
cargo = { path = "" }
-cargo-credential = { version = "0.3.0", path = "credential/cargo-credential" }
+cargo-credential = { version = "0.4.0", path = "credential/cargo-credential" }
cargo-credential-libsecret = { version = "0.3.1", path = "credential/cargo-credential-libsecret" }
cargo-credential-wincred = { version = "0.3.0", path = "credential/cargo-credential-wincred" }
cargo-credential-macos-keychain = { version = "0.3.0", path = "credential/cargo-credential-macos-keychain" }
@@ -27,20 +30,20 @@ cargo-platform = { path = "crates/cargo-platform", version = "0.1.4" }
cargo-test-macro = { path = "crates/cargo-test-macro" }
cargo-test-support = { path = "crates/cargo-test-support" }
cargo-util = { version = "0.2.6", path = "crates/cargo-util" }
-cargo_metadata = "0.14.0"
-clap = "4.3.19"
+cargo_metadata = "0.17.0"
+clap = "4.4.6"
+color-print = "0.3.4"
core-foundation = { version = "0.9.3", features = ["mac_os_10_7_support"] }
-crates-io = { version = "0.38.0", path = "crates/crates-io" }
+crates-io = { version = "0.39.0", path = "crates/crates-io" }
criterion = { version = "0.5.1", features = ["html_reports"] }
curl = "0.4.44"
-curl-sys = "0.4.65"
-filetime = "0.2.21"
-flate2 = { version = "1.0.26", default-features = false, features = ["zlib"] }
-fwdansi = "1.1.0"
-git2 = "0.17.2"
-git2-curl = "0.18.0"
-gix = { version = "0.45.1", default-features = false, features = ["blocking-http-transport-curl", "progress-tree"] }
-gix-features-for-configuration-only = { version = "0.30.0", package = "gix-features", features = [ "parallel" ] }
+curl-sys = "0.4.68"
+filetime = "0.2.22"
+flate2 = { version = "1.0.27", default-features = false, features = ["zlib"] }
+git2 = "0.18.0"
+git2-curl = "0.19.0"
+gix = { version = "0.54.1", default-features = false, features = ["blocking-http-transport-curl", "progress-tree", "revision"] }
+gix-features-for-configuration-only = { version = "0.35.0", package = "gix-features", features = [ "parallel" ] }
glob = "0.3.1"
handlebars = { version = "3.5.5", features = ["dir_source"] }
hex = "0.4.3"
@@ -53,15 +56,14 @@ im-rc = "15.1.0"
indexmap = "2"
itertools = "0.10.0"
jobserver = "0.1.26"
-lazy_static = "1.4.0"
lazycell = "1.3.0"
-libc = "0.2.147"
-libgit2-sys = "0.15.2"
+libc = "0.2.148"
+libgit2-sys = "0.16.1"
libloading = "0.8.0"
-memchr = "2.5.0"
+memchr = "2.6.2"
miow = "0.6.0"
opener = "0.6.1"
-openssl ="0.10.55"
+openssl ="0.10.57"
os_info = "3.7.0"
pasetors = { version = "0.6.7", features = ["v3", "paserk", "std", "serde"] }
pathdiff = "0.2"
@@ -75,36 +77,35 @@ rustfix = "0.6.1"
same-file = "1.0.6"
security-framework = "2.9.2"
semver = { version = "1.0.18", features = ["serde"] }
-serde = "1.0.171"
+serde = "1.0.188"
+serde-untagged = "0.1.1"
serde-value = "0.7.0"
serde_ignored = "0.1.9"
-serde_json = "1.0.104"
+serde_json = "1.0.105"
sha1 = "0.10.5"
sha2 = "0.10.7"
shell-escape = "0.1.5"
-snapbox = { version = "0.4.11", features = ["diff", "path"] }
-strip-ansi-escapes = "0.1.1"
-syn = { version = "2.0.28", features = ["extra-traits", "full"] }
-tar = { version = "0.4.39", default-features = false }
-tempfile = "3.7.0"
-termcolor = "1.2.0"
-thiserror = "1.0.44"
+snapbox = { version = "0.4.13", features = ["diff", "path"] }
+syn = { version = "2.0.29", features = ["extra-traits", "full"] }
+tar = { version = "0.4.40", default-features = false }
+tempfile = "3.8.0"
+thiserror = "1.0.47"
time = { version = "0.3", features = ["parsing", "formatting", "serde"] }
toml = "0.7.6"
toml_edit = "0.19.14"
tracing = "0.1.37"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
-unicase = "2.6.0"
+unicase = "2.7.0"
unicode-width = "0.1.10"
unicode-xid = "0.2.4"
-url = "2.4.0"
+url = "2.4.1"
varisat = "0.2.2"
walkdir = "2.3.3"
windows-sys = "0.48"
[package]
name = "cargo"
-version = "0.74.0"
+version = "0.75.0"
edition.workspace = true
license.workspace = true
homepage = "https://crates.io"
@@ -119,6 +120,8 @@ name = "cargo"
path = "src/cargo/lib.rs"
[dependencies]
+anstream.workspace = true
+anstyle.workspace = true
anyhow.workspace = true
base64.workspace = true
bytesize.workspace = true
@@ -128,6 +131,7 @@ cargo-credential-libsecret.workspace = true
cargo-credential-macos-keychain.workspace = true
cargo-credential-wincred.workspace = true
cargo-util.workspace = true
+color-print.workspace = true
clap = { workspace = true, features = ["wrap_help"] }
crates-io.workspace = true
curl = { workspace = true, features = ["http2"] }
@@ -162,16 +166,15 @@ rand.workspace = true
rustfix.workspace = true
semver.workspace = true
serde = { workspace = true, features = ["derive"] }
+serde-untagged.workspace = true
serde-value.workspace = true
serde_ignored.workspace = true
serde_json = { workspace = true, features = ["raw_value"] }
sha1.workspace = true
shell-escape.workspace = true
-strip-ansi-escapes.workspace = true
syn.workspace = true
tar.workspace = true
tempfile.workspace = true
-termcolor.workspace = true
time.workspace = true
toml.workspace = true
toml_edit.workspace = true
@@ -186,9 +189,6 @@ walkdir.workspace = true
[target.'cfg(not(windows))'.dependencies]
openssl = { workspace = true, optional = true }
-[target.'cfg(windows)'.dependencies]
-fwdansi.workspace = true
-
[target.'cfg(windows)'.dependencies.windows-sys]
workspace = true
features = [
diff --git a/src/tools/cargo/benches/benchsuite/Cargo.toml b/src/tools/cargo/benches/benchsuite/Cargo.toml
index c15798787..81413e761 100644
--- a/src/tools/cargo/benches/benchsuite/Cargo.toml
+++ b/src/tools/cargo/benches/benchsuite/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "benchsuite"
version = "0.0.0"
+rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage = "https://github.com/rust-lang/cargo"
diff --git a/src/tools/cargo/benches/benchsuite/benches/resolve.rs b/src/tools/cargo/benches/benchsuite/benches/resolve.rs
index d03cd620e..f5e28322e 100644
--- a/src/tools/cargo/benches/benchsuite/benches/resolve.rs
+++ b/src/tools/cargo/benches/benchsuite/benches/resolve.rs
@@ -25,22 +25,24 @@ struct ResolveInfo<'cfg> {
fn do_resolve<'cfg>(config: &'cfg Config, ws_root: &Path) -> ResolveInfo<'cfg> {
let requested_kinds = [CompileKind::Host];
let ws = Workspace::new(&ws_root.join("Cargo.toml"), config).unwrap();
- let target_data = RustcTargetData::new(&ws, &requested_kinds).unwrap();
+ let mut target_data = RustcTargetData::new(&ws, &requested_kinds).unwrap();
let cli_features = CliFeatures::from_command_line(&[], false, true).unwrap();
let pkgs = cargo::ops::Packages::Default;
let specs = pkgs.to_package_id_specs(&ws).unwrap();
let has_dev_units = HasDevUnits::Yes;
let force_all_targets = ForceAllTargets::No;
+ let max_rust_version = None;
// Do an initial run to download anything necessary so that it does
// not confuse criterion's warmup.
let ws_resolve = cargo::ops::resolve_ws_with_opts(
&ws,
- &target_data,
+ &mut target_data,
&requested_kinds,
&cli_features,
&specs,
has_dev_units,
force_all_targets,
+ max_rust_version,
)
.unwrap();
ResolveInfo {
@@ -82,6 +84,7 @@ fn resolve_ws(c: &mut Criterion) {
force_all_targets,
..
} = lazy_info.get_or_insert_with(|| do_resolve(&config, &ws_root));
+ let max_rust_version = None;
b.iter(|| {
cargo::ops::resolve_ws_with_opts(
ws,
@@ -91,6 +94,7 @@ fn resolve_ws(c: &mut Criterion) {
specs,
*has_dev_units,
*force_all_targets,
+ max_rust_version,
)
.unwrap();
})
diff --git a/src/tools/cargo/benches/capture/Cargo.toml b/src/tools/cargo/benches/capture/Cargo.toml
index e42fe70e2..e300815d5 100644
--- a/src/tools/cargo/benches/capture/Cargo.toml
+++ b/src/tools/cargo/benches/capture/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "capture"
version = "0.1.0"
+rust-version.workspace = true
edition.workspace = true
license.workspace = true
description = "Tool for capturing a real-world workspace for benchmarking."
diff --git a/src/tools/cargo/clippy.toml b/src/tools/cargo/clippy.toml
index 050cc8716..f50e36588 100644
--- a/src/tools/cargo/clippy.toml
+++ b/src/tools/cargo/clippy.toml
@@ -1,8 +1,8 @@
allow-print-in-tests = true
allow-dbg-in-tests = true
disallowed-methods = [
- { path = "std::env::var", reason = "Use `Config::get_env` instead. See rust-lang/cargo#11588" },
- { path = "std::env::var_os", reason = "Use `Config::get_env_os` instead. See rust-lang/cargo#11588" },
- { path = "std::env::vars", reason = "Not recommended to use in Cargo. See rust-lang/cargo#11588" },
- { path = "std::env::vars_os", reason = "Not recommended to use in Cargo. See rust-lang/cargo#11588" },
+ { path = "std::env::var", reason = "use `Config::get_env` instead. See rust-lang/cargo#11588" },
+ { path = "std::env::var_os", reason = "use `Config::get_env_os` instead. See rust-lang/cargo#11588" },
+ { path = "std::env::vars", reason = "not recommended to use in Cargo. See rust-lang/cargo#11588" },
+ { path = "std::env::vars_os", reason = "not recommended to use in Cargo. See rust-lang/cargo#11588" },
]
diff --git a/src/tools/cargo/crates/cargo-platform/Cargo.toml b/src/tools/cargo/crates/cargo-platform/Cargo.toml
index e7f22cf87..016ead686 100644
--- a/src/tools/cargo/crates/cargo-platform/Cargo.toml
+++ b/src/tools/cargo/crates/cargo-platform/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "cargo-platform"
-version = "0.1.4"
+version = "0.1.5"
edition.workspace = true
license.workspace = true
homepage = "https://github.com/rust-lang/cargo"
diff --git a/src/tools/cargo/crates/cargo-platform/examples/matches.rs b/src/tools/cargo/crates/cargo-platform/examples/matches.rs
index 9ad5d10dd..1b438fb11 100644
--- a/src/tools/cargo/crates/cargo-platform/examples/matches.rs
+++ b/src/tools/cargo/crates/cargo-platform/examples/matches.rs
@@ -35,8 +35,8 @@ fn get_target() -> String {
.expect("rustc failed to run");
let stdout = String::from_utf8(output.stdout).unwrap();
for line in stdout.lines() {
- if line.starts_with("host: ") {
- return String::from(&line[6..]);
+ if let Some(line) = line.strip_prefix("host: ") {
+ return String::from(line);
}
}
panic!("Failed to find host: {}", stdout);
diff --git a/src/tools/cargo/crates/cargo-platform/src/error.rs b/src/tools/cargo/crates/cargo-platform/src/error.rs
index bf4b35f27..2d5b315f9 100644
--- a/src/tools/cargo/crates/cargo-platform/src/error.rs
+++ b/src/tools/cargo/crates/cargo-platform/src/error.rs
@@ -21,7 +21,7 @@ pub enum ParseErrorKind {
}
impl fmt::Display for ParseError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"failed to parse `{}` as a cfg expression: {}",
@@ -31,7 +31,7 @@ impl fmt::Display for ParseError {
}
impl fmt::Display for ParseErrorKind {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ParseErrorKind::*;
match self {
UnterminatedString => write!(f, "unterminated string in cfg"),
diff --git a/src/tools/cargo/crates/cargo-platform/src/lib.rs b/src/tools/cargo/crates/cargo-platform/src/lib.rs
index 0a3dcf1af..7911e484e 100644
--- a/src/tools/cargo/crates/cargo-platform/src/lib.rs
+++ b/src/tools/cargo/crates/cargo-platform/src/lib.rs
@@ -126,8 +126,7 @@ impl FromStr for Platform {
type Err = ParseError;
fn from_str(s: &str) -> Result<Platform, ParseError> {
- if s.starts_with("cfg(") && s.ends_with(')') {
- let s = &s[4..s.len() - 1];
+ if let Some(s) = s.strip_prefix("cfg(").and_then(|s| s.strip_suffix(')')) {
s.parse().map(Platform::Cfg)
} else {
Platform::validate_named_platform(s)?;
diff --git a/src/tools/cargo/crates/cargo-test-macro/Cargo.toml b/src/tools/cargo/crates/cargo-test-macro/Cargo.toml
index b5da0522f..1e81ab314 100644
--- a/src/tools/cargo/crates/cargo-test-macro/Cargo.toml
+++ b/src/tools/cargo/crates/cargo-test-macro/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "cargo-test-macro"
version = "0.1.0"
+rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage = "https://github.com/rust-lang/cargo"
diff --git a/src/tools/cargo/crates/cargo-test-macro/src/lib.rs b/src/tools/cargo/crates/cargo-test-macro/src/lib.rs
index aa06f477d..937fbce6b 100644
--- a/src/tools/cargo/crates/cargo-test-macro/src/lib.rs
+++ b/src/tools/cargo/crates/cargo-test-macro/src/lib.rs
@@ -1,5 +1,3 @@
-extern crate proc_macro;
-
use proc_macro::*;
use std::process::Command;
use std::sync::Once;
diff --git a/src/tools/cargo/crates/cargo-test-support/Cargo.toml b/src/tools/cargo/crates/cargo-test-support/Cargo.toml
index 085041aff..fc32e1c9c 100644
--- a/src/tools/cargo/crates/cargo-test-support/Cargo.toml
+++ b/src/tools/cargo/crates/cargo-test-support/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "cargo-test-support"
version = "0.1.0"
+rust-version.workspace = true
license.workspace = true
edition.workspace = true
publish = false
@@ -9,6 +10,8 @@ publish = false
doctest = false
[dependencies]
+anstream.workspace = true
+anstyle.workspace = true
anyhow.workspace = true
cargo-test-macro.workspace = true
cargo-util.workspace = true
@@ -18,13 +21,11 @@ flate2.workspace = true
git2.workspace = true
glob.workspace = true
itertools.workspace = true
-lazy_static.workspace = true
pasetors.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
snapbox.workspace = true
tar.workspace = true
-termcolor.workspace = true
time.workspace = true
toml.workspace = true
url.workspace = true
diff --git a/src/tools/cargo/crates/cargo-test-support/src/compare.rs b/src/tools/cargo/crates/cargo-test-support/src/compare.rs
index 21eb64d28..09e3a5a0c 100644
--- a/src/tools/cargo/crates/cargo-test-support/src/compare.rs
+++ b/src/tools/cargo/crates/cargo-test-support/src/compare.rs
@@ -206,6 +206,7 @@ fn substitute_macros(input: &str) -> String {
("[UPDATING]", " Updating"),
("[ADDING]", " Adding"),
("[REMOVING]", " Removing"),
+ ("[REMOVED]", " Removed"),
("[DOCTEST]", " Doc-tests"),
("[PACKAGING]", " Packaging"),
("[PACKAGED]", " Packaged"),
diff --git a/src/tools/cargo/crates/cargo-test-support/src/diff.rs b/src/tools/cargo/crates/cargo-test-support/src/diff.rs
index f3b283b10..3fedc839b 100644
--- a/src/tools/cargo/crates/cargo-test-support/src/diff.rs
+++ b/src/tools/cargo/crates/cargo-test-support/src/diff.rs
@@ -7,7 +7,6 @@
use std::fmt;
use std::io::Write;
-use termcolor::{Ansi, Color, ColorSpec, NoColor, WriteColor};
/// A single line change to be applied to the original.
#[derive(Debug, Eq, PartialEq)]
@@ -111,42 +110,35 @@ where
}
pub fn render_colored_changes<T: fmt::Display>(changes: &[Change<T>]) -> String {
- // termcolor is not very ergonomic, but I don't want to bring in another dependency.
- let mut red = ColorSpec::new();
- red.set_fg(Some(Color::Red));
- let mut green = ColorSpec::new();
- green.set_fg(Some(Color::Green));
- let mut dim = ColorSpec::new();
- dim.set_dimmed(true);
- let mut v = Vec::new();
- let mut result: Box<dyn WriteColor> = if crate::is_ci() {
+ // anstyle is not very ergonomic, but I don't want to bring in another dependency.
+ let red = anstyle::AnsiColor::Red.on_default().render();
+ let green = anstyle::AnsiColor::Green.on_default().render();
+ let dim = (anstyle::Style::new() | anstyle::Effects::DIMMED).render();
+ let bold = (anstyle::Style::new() | anstyle::Effects::BOLD).render();
+ let reset = anstyle::Reset.render();
+
+ let choice = if crate::is_ci() {
// Don't use color on CI. Even though GitHub can display colors, it
// makes reading the raw logs more difficult.
- Box::new(NoColor::new(&mut v))
+ anstream::ColorChoice::Never
} else {
- Box::new(Ansi::new(&mut v))
+ anstream::AutoStream::choice(&std::io::stdout())
};
+ let mut buffer = anstream::AutoStream::new(Vec::new(), choice);
for change in changes {
let (nums, sign, color, text) = match change {
- Change::Add(i, s) => (format!(" {:<4} ", i), '+', &green, s),
- Change::Remove(i, s) => (format!("{:<4} ", i), '-', &red, s),
- Change::Keep(x, y, s) => (format!("{:<4}{:<4} ", x, y), ' ', &dim, s),
+ Change::Add(i, s) => (format!(" {:<4} ", i), '+', green, s),
+ Change::Remove(i, s) => (format!("{:<4} ", i), '-', red, s),
+ Change::Keep(x, y, s) => (format!("{:<4}{:<4} ", x, y), ' ', dim, s),
};
- result.set_color(&dim).unwrap();
- write!(result, "{}", nums).unwrap();
- let mut bold = color.clone();
- bold.set_bold(true);
- result.set_color(&bold).unwrap();
- write!(result, "{}", sign).unwrap();
- result.reset().unwrap();
- result.set_color(&color).unwrap();
- write!(result, "{}", text).unwrap();
- result.reset().unwrap();
- writeln!(result).unwrap();
+ write!(
+ buffer,
+ "{dim}{nums}{reset}{bold}{sign}{reset}{color}{text}{reset}"
+ )
+ .unwrap();
}
- drop(result);
- String::from_utf8(v).unwrap()
+ String::from_utf8(buffer.into_inner()).unwrap()
}
#[cfg(test)]
diff --git a/src/tools/cargo/crates/cargo-test-support/src/git.rs b/src/tools/cargo/crates/cargo-test-support/src/git.rs
index 6fde96467..236011ca1 100644
--- a/src/tools/cargo/crates/cargo-test-support/src/git.rs
+++ b/src/tools/cargo/crates/cargo-test-support/src/git.rs
@@ -10,7 +10,7 @@ Example:
```
let git_project = git::new("dep1", |project| {
project
- .file("Cargo.toml", &basic_manifest("dep1"))
+ .file("Cargo.toml", &basic_manifest("dep1", "1.0.0"))
.file("src/lib.rs", r#"pub fn f() { println!("hi!"); } "#)
});
@@ -177,25 +177,8 @@ where
/// Add all files in the working directory to the git index.
pub fn add(repo: &git2::Repository) {
- // FIXME(libgit2/libgit2#2514): apparently, `add_all` will add all submodules
- // as well, and then fail because they're directories. As a stop-gap, we just
- // ignore all submodules.
- let mut s = t!(repo.submodules());
- for submodule in s.iter_mut() {
- t!(submodule.add_to_index(false));
- }
let mut index = t!(repo.index());
- t!(index.add_all(
- ["*"].iter(),
- git2::IndexAddOption::DEFAULT,
- Some(
- &mut (|a, _b| if s.iter().any(|s| a.starts_with(s.path())) {
- 1
- } else {
- 0
- })
- )
- ));
+ t!(index.add_all(["*"].iter(), git2::IndexAddOption::DEFAULT, None));
t!(index.write());
}
diff --git a/src/tools/cargo/crates/cargo-test-support/src/lib.rs b/src/tools/cargo/crates/cargo-test-support/src/lib.rs
index a2fa54c60..1a8742720 100644
--- a/src/tools/cargo/crates/cargo-test-support/src/lib.rs
+++ b/src/tools/cargo/crates/cargo-test-support/src/lib.rs
@@ -12,6 +12,7 @@ use std::os;
use std::path::{Path, PathBuf};
use std::process::{Command, Output};
use std::str;
+use std::sync::OnceLock;
use std::time::{self, Duration};
use anyhow::{bail, Result};
@@ -569,6 +570,7 @@ pub struct Execs {
expect_stdout_contains_n: Vec<(String, usize)>,
expect_stdout_not_contains: Vec<String>,
expect_stderr_not_contains: Vec<String>,
+ expect_stdout_unordered: Vec<String>,
expect_stderr_unordered: Vec<String>,
expect_stderr_with_without: Vec<(Vec<String>, Vec<String>)>,
expect_json: Option<String>,
@@ -670,6 +672,15 @@ impl Execs {
self
}
+ /// Verifies that all of the stdout output is equal to the given lines,
+ /// ignoring the order of the lines.
+ ///
+ /// See [`Execs::with_stderr_unordered`] for more details.
+ pub fn with_stdout_unordered<S: ToString>(&mut self, expected: S) -> &mut Self {
+ self.expect_stdout_unordered.push(expected.to_string());
+ self
+ }
+
/// Verifies that all of the stderr output is equal to the given lines,
/// ignoring the order of the lines.
///
@@ -838,7 +849,7 @@ impl Execs {
/// Enables nightly features for testing
///
/// The list of reasons should be why nightly cargo is needed. If it is
- /// becuase of an unstable feature put the name of the feature as the reason,
+ /// because of an unstable feature put the name of the feature as the reason,
/// e.g. `&["print-im-a-teapot"]`
pub fn masquerade_as_nightly_cargo(&mut self, reasons: &[&str]) -> &mut Self {
if let Some(ref mut p) = self.process_builder {
@@ -931,6 +942,7 @@ impl Execs {
&& self.expect_stdout_contains_n.is_empty()
&& self.expect_stdout_not_contains.is_empty()
&& self.expect_stderr_not_contains.is_empty()
+ && self.expect_stdout_unordered.is_empty()
&& self.expect_stderr_unordered.is_empty()
&& self.expect_stderr_with_without.is_empty()
&& self.expect_json.is_none()
@@ -1035,6 +1047,9 @@ impl Execs {
for expect in self.expect_stderr_not_contains.iter() {
compare::match_does_not_contain(expect, stderr, cwd)?;
}
+ for expect in self.expect_stdout_unordered.iter() {
+ compare::match_unordered(expect, stdout, cwd)?;
+ }
for expect in self.expect_stderr_unordered.iter() {
compare::match_unordered(expect, stderr, cwd)?;
}
@@ -1074,6 +1089,7 @@ pub fn execs() -> Execs {
expect_stdout_contains_n: Vec::new(),
expect_stdout_not_contains: Vec::new(),
expect_stderr_not_contains: Vec::new(),
+ expect_stdout_unordered: Vec::new(),
expect_stderr_unordered: Vec::new(),
expect_stderr_with_without: Vec::new(),
expect_json: None,
@@ -1157,13 +1173,14 @@ impl RustcInfo {
}
}
-lazy_static::lazy_static! {
- static ref RUSTC_INFO: RustcInfo = RustcInfo::new();
+fn rustc_info() -> &'static RustcInfo {
+ static RUSTC_INFO: OnceLock<RustcInfo> = OnceLock::new();
+ RUSTC_INFO.get_or_init(RustcInfo::new)
}
/// The rustc host such as `x86_64-unknown-linux-gnu`.
pub fn rustc_host() -> &'static str {
- &RUSTC_INFO.host
+ &rustc_info().host
}
/// The host triple suitable for use in a cargo environment variable (uppercased).
@@ -1172,7 +1189,7 @@ pub fn rustc_host_env() -> String {
}
pub fn is_nightly() -> bool {
- let vv = &RUSTC_INFO.verbose_version;
+ let vv = &rustc_info().verbose_version;
// CARGO_TEST_DISABLE_NIGHTLY is set in rust-lang/rust's CI so that all
// nightly-only tests are disabled there. Otherwise, it could make it
// difficult to land changes which would need to be made simultaneously in
@@ -1194,7 +1211,7 @@ fn _process(t: &OsStr) -> ProcessBuilder {
/// Enable nightly features for testing
pub trait ChannelChanger {
/// The list of reasons should be why nightly cargo is needed. If it is
- /// becuase of an unstable feature put the name of the feature as the reason,
+ /// because of an unstable feature put the name of the feature as the reason,
/// e.g. `&["print-im-a-teapot"]`.
fn masquerade_as_nightly_cargo(self, _reasons: &[&str]) -> Self;
}
@@ -1225,28 +1242,27 @@ pub trait TestEnv: Sized {
if env::var_os("RUSTUP_TOOLCHAIN").is_some() {
// Override the PATH to avoid executing the rustup wrapper thousands
// of times. This makes the testsuite run substantially faster.
- lazy_static::lazy_static! {
- static ref RUSTC_DIR: PathBuf = {
- match ProcessBuilder::new("rustup")
- .args(&["which", "rustc"])
- .exec_with_output()
- {
- Ok(output) => {
- let s = str::from_utf8(&output.stdout).expect("utf8").trim();
- let mut p = PathBuf::from(s);
- p.pop();
- p
- }
- Err(e) => {
- panic!("RUSTUP_TOOLCHAIN was set, but could not run rustup: {}", e);
- }
+ static RUSTC_DIR: OnceLock<PathBuf> = OnceLock::new();
+ let rustc_dir = RUSTC_DIR.get_or_init(|| {
+ match ProcessBuilder::new("rustup")
+ .args(&["which", "rustc"])
+ .exec_with_output()
+ {
+ Ok(output) => {
+ let s = str::from_utf8(&output.stdout).expect("utf8").trim();
+ let mut p = PathBuf::from(s);
+ p.pop();
+ p
}
- };
- }
+ Err(e) => {
+ panic!("RUSTUP_TOOLCHAIN was set, but could not run rustup: {}", e);
+ }
+ }
+ });
let path = env::var_os("PATH").unwrap_or_default();
let paths = env::split_paths(&path);
let new_path =
- env::join_paths(std::iter::once(RUSTC_DIR.clone()).chain(paths)).unwrap();
+ env::join_paths(std::iter::once(rustc_dir.clone()).chain(paths)).unwrap();
self = self.env("PATH", new_path);
}
@@ -1408,11 +1424,14 @@ pub fn is_coarse_mtime() -> bool {
/// Architectures that do not have a modern processor, hardware emulation, etc.
/// This provides a way for those setups to increase the cut off for all the time based test.
pub fn slow_cpu_multiplier(main: u64) -> Duration {
- lazy_static::lazy_static! {
- static ref SLOW_CPU_MULTIPLIER: u64 =
- env::var("CARGO_TEST_SLOW_CPU_MULTIPLIER").ok().and_then(|m| m.parse().ok()).unwrap_or(1);
- }
- Duration::from_secs(*SLOW_CPU_MULTIPLIER * main)
+ static SLOW_CPU_MULTIPLIER: OnceLock<u64> = OnceLock::new();
+ let slow_cpu_multiplier = SLOW_CPU_MULTIPLIER.get_or_init(|| {
+ env::var("CARGO_TEST_SLOW_CPU_MULTIPLIER")
+ .ok()
+ .and_then(|m| m.parse().ok())
+ .unwrap_or(1)
+ });
+ Duration::from_secs(slow_cpu_multiplier * main)
}
#[cfg(windows)]
diff --git a/src/tools/cargo/crates/cargo-test-support/src/publish.rs b/src/tools/cargo/crates/cargo-test-support/src/publish.rs
index dccc8356d..f850330c1 100644
--- a/src/tools/cargo/crates/cargo-test-support/src/publish.rs
+++ b/src/tools/cargo/crates/cargo-test-support/src/publish.rs
@@ -131,8 +131,11 @@ pub fn validate_crate_contents(
(name, contents)
})
.collect();
- assert!(expected_crate_name.ends_with(".crate"));
- let base_crate_name = Path::new(&expected_crate_name[..expected_crate_name.len() - 6]);
+ let base_crate_name = Path::new(
+ expected_crate_name
+ .strip_suffix(".crate")
+ .expect("must end with .crate"),
+ );
let actual_files: HashSet<PathBuf> = files.keys().cloned().collect();
let expected_files: HashSet<PathBuf> = expected_files
.iter()
diff --git a/src/tools/cargo/crates/cargo-test-support/src/registry.rs b/src/tools/cargo/crates/cargo-test-support/src/registry.rs
index 27c319656..853829c56 100644
--- a/src/tools/cargo/crates/cargo-test-support/src/registry.rs
+++ b/src/tools/cargo/crates/cargo-test-support/src/registry.rs
@@ -549,7 +549,9 @@ pub struct Dependency {
name: String,
vers: String,
kind: String,
- artifact: Option<(String, Option<String>)>,
+ artifact: Option<String>,
+ bindep_target: Option<String>,
+ lib: bool,
target: Option<String>,
features: Vec<String>,
registry: Option<String>,
@@ -779,6 +781,7 @@ impl HttpServer {
let buf = buf.get_mut();
write!(buf, "HTTP/1.1 {}\r\n", response.code).unwrap();
write!(buf, "Content-Length: {}\r\n", response.body.len()).unwrap();
+ write!(buf, "Connection: close\r\n").unwrap();
for header in response.headers {
write!(buf, "{}\r\n", header).unwrap();
}
@@ -788,7 +791,7 @@ impl HttpServer {
}
}
- fn check_authorized(&self, req: &Request, mutation: Option<Mutation>) -> bool {
+ fn check_authorized(&self, req: &Request, mutation: Option<Mutation<'_>>) -> bool {
let (private_key, private_key_subject) = if mutation.is_some() || self.auth_required {
match &self.token {
Token::Plaintext(token) => return Some(token) == req.authorization.as_ref(),
@@ -830,7 +833,8 @@ impl HttpServer {
url: &'a str,
kip: &'a str,
}
- let footer: Footer = t!(serde_json::from_slice(untrusted_token.untrusted_footer()).ok());
+ let footer: Footer<'_> =
+ t!(serde_json::from_slice(untrusted_token.untrusted_footer()).ok());
if footer.kip != paserk_pub_key_id {
return false;
}
@@ -844,7 +848,6 @@ impl HttpServer {
if footer.url != "https://github.com/rust-lang/crates.io-index"
&& footer.url != &format!("sparse+http://{}/index/", self.addr.to_string())
{
- dbg!(footer.url);
return false;
}
@@ -860,20 +863,18 @@ impl HttpServer {
_challenge: Option<&'a str>, // todo: PASETO with challenges
v: Option<u8>,
}
- let message: Message = t!(serde_json::from_str(trusted_token.payload()).ok());
+ let message: Message<'_> = t!(serde_json::from_str(trusted_token.payload()).ok());
let token_time = t!(OffsetDateTime::parse(message.iat, &Rfc3339).ok());
let now = OffsetDateTime::now_utc();
if (now - token_time) > Duration::MINUTE {
return false;
}
if private_key_subject.as_deref() != message.sub {
- dbg!(message.sub);
return false;
}
// - If the claim v is set, that it has the value of 1.
if let Some(v) = message.v {
if v != 1 {
- dbg!(message.v);
return false;
}
}
@@ -883,22 +884,18 @@ impl HttpServer {
if let Some(mutation) = mutation {
// - That the operation matches the mutation field and is one of publish, yank, or unyank.
if message.mutation != Some(mutation.mutation) {
- dbg!(message.mutation);
return false;
}
// - That the package, and version match the request.
if message.name != mutation.name {
- dbg!(message.name);
return false;
}
if message.vers != mutation.vers {
- dbg!(message.vers);
return false;
}
// - If the mutation is publish, that the version has not already been published, and that the hash matches the request.
if mutation.mutation == "publish" {
if message.cksum != mutation.cksum {
- dbg!(message.cksum);
return false;
}
}
@@ -1409,13 +1406,20 @@ impl Package {
(true, Some("alternative")) => None,
_ => panic!("registry_dep currently only supports `alternative`"),
};
+ let artifact = if let Some(artifact) = &dep.artifact {
+ serde_json::json!([artifact])
+ } else {
+ serde_json::json!(null)
+ };
serde_json::json!({
"name": dep.name,
"req": dep.vers,
"features": dep.features,
"default_features": true,
"target": dep.target,
- "artifact": dep.artifact,
+ "artifact": artifact,
+ "bindep_target": dep.bindep_target,
+ "lib": dep.lib,
"optional": dep.optional,
"kind": dep.kind,
"registry": registry_url,
@@ -1536,11 +1540,14 @@ impl Package {
"#,
target, kind, dep.name, dep.vers
));
- if let Some((artifact, target)) = &dep.artifact {
+ if let Some(artifact) = &dep.artifact {
manifest.push_str(&format!("artifact = \"{}\"\n", artifact));
- if let Some(target) = &target {
- manifest.push_str(&format!("target = \"{}\"\n", target))
- }
+ }
+ if let Some(target) = &dep.bindep_target {
+ manifest.push_str(&format!("target = \"{}\"\n", target));
+ }
+ if dep.lib {
+ manifest.push_str("lib = true\n");
}
if let Some(registry) = &dep.registry {
assert_eq!(registry, "alternative");
@@ -1617,6 +1624,8 @@ impl Dependency {
vers: vers.to_string(),
kind: "normal".to_string(),
artifact: None,
+ bindep_target: None,
+ lib: false,
target: None,
features: Vec::new(),
package: None,
@@ -1646,7 +1655,8 @@ impl Dependency {
/// Change the artifact to be of the given kind, like "bin", or "staticlib",
/// along with a specific target triple if provided.
pub fn artifact(&mut self, kind: &str, target: Option<String>) -> &mut Self {
- self.artifact = Some((kind.to_string(), target));
+ self.artifact = Some(kind.to_string());
+ self.bindep_target = target;
self
}
diff --git a/src/tools/cargo/crates/cargo-util/Cargo.toml b/src/tools/cargo/crates/cargo-util/Cargo.toml
index 99a59422d..cba00f917 100644
--- a/src/tools/cargo/crates/cargo-util/Cargo.toml
+++ b/src/tools/cargo/crates/cargo-util/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "cargo-util"
-version = "0.2.6"
+version = "0.2.7"
+rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage = "https://github.com/rust-lang/cargo"
diff --git a/src/tools/cargo/crates/cargo-util/src/paths.rs b/src/tools/cargo/crates/cargo-util/src/paths.rs
index ce6755859..888ca1af5 100644
--- a/src/tools/cargo/crates/cargo-util/src/paths.rs
+++ b/src/tools/cargo/crates/cargo-util/src/paths.rs
@@ -4,7 +4,7 @@ use anyhow::{Context, Result};
use filetime::FileTime;
use std::env;
use std::ffi::{OsStr, OsString};
-use std::fs::{self, File, OpenOptions};
+use std::fs::{self, File, Metadata, OpenOptions};
use std::io;
use std::io::prelude::*;
use std::iter;
@@ -136,6 +136,24 @@ pub fn resolve_executable(exec: &Path) -> Result<PathBuf> {
}
}
+/// Returns metadata for a file (follows symlinks).
+///
+/// Equivalent to [`std::fs::metadata`] with better error messages.
+pub fn metadata<P: AsRef<Path>>(path: P) -> Result<Metadata> {
+ let path = path.as_ref();
+ std::fs::metadata(path)
+ .with_context(|| format!("failed to load metadata for path `{}`", path.display()))
+}
+
+/// Returns metadata for a file without following symlinks.
+///
+/// Equivalent to [`std::fs::metadata`] with better error messages.
+pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> Result<Metadata> {
+ let path = path.as_ref();
+ std::fs::symlink_metadata(path)
+ .with_context(|| format!("failed to load metadata for path `{}`", path.display()))
+}
+
/// Reads a file to a string.
///
/// Equivalent to [`std::fs::read_to_string`] with better error messages.
@@ -216,16 +234,14 @@ pub fn open<P: AsRef<Path>>(path: P) -> Result<File> {
/// Returns the last modification time of a file.
pub fn mtime(path: &Path) -> Result<FileTime> {
- let meta =
- fs::metadata(path).with_context(|| format!("failed to stat `{}`", path.display()))?;
+ let meta = metadata(path)?;
Ok(FileTime::from_last_modification_time(&meta))
}
/// Returns the maximum mtime of the given path, recursing into
/// subdirectories, and following symlinks.
pub fn mtime_recursive(path: &Path) -> Result<FileTime> {
- let meta =
- fs::metadata(path).with_context(|| format!("failed to stat `{}`", path.display()))?;
+ let meta = metadata(path)?;
if !meta.is_dir() {
return Ok(FileTime::from_last_modification_time(&meta));
}
@@ -432,10 +448,7 @@ pub fn remove_dir_all<P: AsRef<Path>>(p: P) -> Result<()> {
}
fn _remove_dir_all(p: &Path) -> Result<()> {
- if p.symlink_metadata()
- .with_context(|| format!("could not get metadata for `{}` to remove", p.display()))?
- .is_symlink()
- {
+ if symlink_metadata(p)?.is_symlink() {
return remove_file(p);
}
let entries = p
diff --git a/src/tools/cargo/crates/crates-io/Cargo.toml b/src/tools/cargo/crates/crates-io/Cargo.toml
index 139b8aa97..d06dacdfa 100644
--- a/src/tools/cargo/crates/crates-io/Cargo.toml
+++ b/src/tools/cargo/crates/crates-io/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "crates-io"
-version = "0.38.0"
+version = "0.39.0"
+rust-version.workspace = true
edition.workspace = true
license.workspace = true
repository = "https://github.com/rust-lang/cargo"
diff --git a/src/tools/cargo/crates/crates-io/lib.rs b/src/tools/cargo/crates/crates-io/lib.rs
index 6ce39cefd..757241fd3 100644
--- a/src/tools/cargo/crates/crates-io/lib.rs
+++ b/src/tools/cargo/crates/crates-io/lib.rs
@@ -73,6 +73,16 @@ pub struct NewCrateDependency {
pub registry: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub explicit_name_in_toml: Option<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub artifact: Option<Vec<String>>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub bindep_target: Option<String>,
+ #[serde(default, skip_serializing_if = "is_false")]
+ pub lib: bool,
+}
+
+fn is_false(x: &bool) -> bool {
+ *x == false
}
#[derive(Deserialize)]
@@ -132,7 +142,7 @@ pub enum Error {
#[error(transparent)]
Curl(#[from] curl::Error),
- /// Error from seriailzing the request payload and deserialzing the
+ /// Error from seriailzing the request payload and deserializing the
/// response body (like response body didn't match expected structure).
#[error(transparent)]
Json(#[from] serde_json::Error),
diff --git a/src/tools/cargo/crates/mdman/Cargo.toml b/src/tools/cargo/crates/mdman/Cargo.toml
index ba1d4b462..fd33da3c2 100644
--- a/src/tools/cargo/crates/mdman/Cargo.toml
+++ b/src/tools/cargo/crates/mdman/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "mdman"
version = "0.0.0"
+rust-version.workspace = true
edition.workspace = true
license.workspace = true
description = "Creates a man page page from markdown."
diff --git a/src/tools/cargo/crates/mdman/src/format.rs b/src/tools/cargo/crates/mdman/src/format/mod.rs
index 7bc9781b9..7bc9781b9 100644
--- a/src/tools/cargo/crates/mdman/src/format.rs
+++ b/src/tools/cargo/crates/mdman/src/format/mod.rs
diff --git a/src/tools/cargo/crates/mdman/src/hbs.rs b/src/tools/cargo/crates/mdman/src/hbs.rs
index 81ad7ee45..055eb3f28 100644
--- a/src/tools/cargo/crates/mdman/src/hbs.rs
+++ b/src/tools/cargo/crates/mdman/src/hbs.rs
@@ -12,7 +12,7 @@ use std::path::Path;
type FormatterRef<'a> = &'a (dyn Formatter + Send + Sync);
/// Processes the handlebars template at the given file.
-pub fn expand(file: &Path, formatter: FormatterRef) -> Result<String, Error> {
+pub fn expand(file: &Path, formatter: FormatterRef<'_>) -> Result<String, Error> {
let mut handlebars = Handlebars::new();
handlebars.set_strict_mode(true);
handlebars.register_helper("lower", Box::new(lower));
@@ -174,10 +174,10 @@ impl HelperDef for ManLinkHelper<'_> {
///
/// This sets a variable to a value within the template context.
fn set_decorator(
- d: &Decorator,
- _: &Handlebars,
+ d: &Decorator<'_, '_>,
+ _: &Handlebars<'_>,
_ctx: &Context,
- rc: &mut RenderContext,
+ rc: &mut RenderContext<'_, '_>,
) -> Result<(), RenderError> {
let data_to_set = d.hash();
for (k, v) in data_to_set {
@@ -187,7 +187,7 @@ fn set_decorator(
}
/// Sets a variable to a value within the context.
-fn set_in_context(rc: &mut RenderContext, key: &str, value: serde_json::Value) {
+fn set_in_context(rc: &mut RenderContext<'_, '_>, key: &str, value: serde_json::Value) {
let mut ctx = match rc.context() {
Some(c) => (*c).clone(),
None => Context::wraps(serde_json::Value::Object(serde_json::Map::new())).unwrap(),
@@ -201,7 +201,7 @@ fn set_in_context(rc: &mut RenderContext, key: &str, value: serde_json::Value) {
}
/// Removes a variable from the context.
-fn remove_from_context(rc: &mut RenderContext, key: &str) {
+fn remove_from_context(rc: &mut RenderContext<'_, '_>, key: &str) {
let ctx = rc.context().expect("cannot remove from null context");
let mut ctx = (*ctx).clone();
if let serde_json::Value::Object(m) = ctx.data_mut() {
diff --git a/src/tools/cargo/crates/mdman/src/lib.rs b/src/tools/cargo/crates/mdman/src/lib.rs
index 01c3c8d31..5cfb3f4ca 100644
--- a/src/tools/cargo/crates/mdman/src/lib.rs
+++ b/src/tools/cargo/crates/mdman/src/lib.rs
@@ -64,7 +64,7 @@ pub fn convert(
type EventIter<'a> = Box<dyn Iterator<Item = (Event<'a>, Range<usize>)> + 'a>;
/// Creates a new markdown parser with the given input.
-pub(crate) fn md_parser(input: &str, url: Option<Url>) -> EventIter {
+pub(crate) fn md_parser(input: &str, url: Option<Url>) -> EventIter<'_> {
let mut options = Options::empty();
options.insert(Options::ENABLE_TABLES);
options.insert(Options::ENABLE_FOOTNOTES);
diff --git a/src/tools/cargo/crates/mdman/src/main.rs b/src/tools/cargo/crates/mdman/src/main.rs
index 2bdf96d72..facaa5120 100644
--- a/src/tools/cargo/crates/mdman/src/main.rs
+++ b/src/tools/cargo/crates/mdman/src/main.rs
@@ -48,7 +48,7 @@ fn run() -> Result<(), Error> {
if same_file::is_same_file(source, &out_path).unwrap_or(false) {
bail!("cannot output to the same file as the source");
}
- println!("Converting {} -> {}", source.display(), out_path.display());
+ eprintln!("Converting {} -> {}", source.display(), out_path.display());
let result = mdman::convert(&source, opts.format, opts.url.clone(), opts.man_map.clone())
.with_context(|| format!("failed to translate {}", source.display()))?;
@@ -98,15 +98,16 @@ fn process_args() -> Result<Options, Error> {
let man = args
.next()
.ok_or_else(|| format_err!("--man requires a value"))?;
- let parts: Vec<_> = man.splitn(2, '=').collect();
- let key_parts: Vec<_> = parts[0].splitn(2, ':').collect();
- if parts.len() != 2 || key_parts.len() != 2 {
- bail!("--man expected value with form name:1=link");
- }
- let section: u8 = key_parts[1].parse().with_context(|| {
- format!("expected unsigned integer for section, got `{}`", parts[1])
+ let parts = man.split_once('=').ok_or_else(|| {
+ anyhow::format_err!("--man expected value with form name:1=link")
+ })?;
+ let key_parts = parts.0.split_once(':').ok_or_else(|| {
+ anyhow::format_err!("--man expected value with form name:1=link")
+ })?;
+ let section: u8 = key_parts.1.parse().with_context(|| {
+ format!("expected unsigned integer for section, got `{}`", parts.1)
})?;
- man_map.insert((key_parts[0].to_string(), section), parts[1].to_string());
+ man_map.insert((key_parts.0.to_string(), section), parts.1.to_string());
}
s => {
sources.push(PathBuf::from(s));
diff --git a/src/tools/cargo/crates/resolver-tests/Cargo.toml b/src/tools/cargo/crates/resolver-tests/Cargo.toml
index 5e69d7367..8750a3d97 100644
--- a/src/tools/cargo/crates/resolver-tests/Cargo.toml
+++ b/src/tools/cargo/crates/resolver-tests/Cargo.toml
@@ -1,12 +1,12 @@
[package]
name = "resolver-tests"
version = "0.0.0"
+rust-version.workspace = true
edition.workspace = true
publish = false
[dependencies]
cargo.workspace = true
cargo-util.workspace = true
-lazy_static.workspace = true
proptest.workspace = true
varisat.workspace = true
diff --git a/src/tools/cargo/crates/resolver-tests/src/lib.rs b/src/tools/cargo/crates/resolver-tests/src/lib.rs
index ab34e8663..9bdeb8674 100644
--- a/src/tools/cargo/crates/resolver-tests/src/lib.rs
+++ b/src/tools/cargo/crates/resolver-tests/src/lib.rs
@@ -7,15 +7,17 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::fmt;
use std::fmt::Write;
use std::rc::Rc;
+use std::sync::OnceLock;
use std::task::Poll;
use std::time::Instant;
use cargo::core::dependency::DepKind;
use cargo::core::resolver::{self, ResolveOpts, VersionPreferences};
-use cargo::core::source::{GitReference, QueryKind, SourceId};
use cargo::core::Resolve;
use cargo::core::{Dependency, PackageId, Registry, Summary};
-use cargo::util::{CargoResult, Config, Graph, IntoUrl};
+use cargo::core::{GitReference, SourceId};
+use cargo::sources::source::QueryKind;
+use cargo::util::{CargoResult, Config, Graph, IntoUrl, RustVersion};
use proptest::collection::{btree_map, vec};
use proptest::prelude::*;
@@ -161,8 +163,8 @@ pub fn resolve_with_config_raw(
if std::thread::panicking() && self.list.len() != self.used.len() {
// we found a case that causes a panic and did not use all of the input.
// lets print the part of the input that was used for minimization.
- println!(
- "{:?}",
+ eprintln!(
+ "Part used befor drop: {:?}",
PrettyPrintRegistry(
self.list
.iter()
@@ -183,11 +185,12 @@ pub fn resolve_with_config_raw(
deps,
&BTreeMap::new(),
None::<&String>,
- None::<&String>,
+ None::<RustVersion>,
)
.unwrap();
let opts = ResolveOpts::everything();
let start = Instant::now();
+ let max_rust_version = None;
let resolve = resolver::resolve(
&[(summary, opts)],
&[],
@@ -195,6 +198,7 @@ pub fn resolve_with_config_raw(
&VersionPreferences::default(),
Some(config),
true,
+ max_rust_version,
);
// The largest test in our suite takes less then 30 sec.
@@ -561,11 +565,11 @@ macro_rules! pkg {
}
fn registry_loc() -> SourceId {
- lazy_static::lazy_static! {
- static ref EXAMPLE_DOT_COM: SourceId =
- SourceId::for_registry(&"https://example.com".into_url().unwrap()).unwrap();
- }
- *EXAMPLE_DOT_COM
+ static EXAMPLE_DOT_COM: OnceLock<SourceId> = OnceLock::new();
+ let example_dot = EXAMPLE_DOT_COM.get_or_init(|| {
+ SourceId::for_registry(&"https://example.com".into_url().unwrap()).unwrap()
+ });
+ *example_dot
}
pub fn pkg<T: ToPkgId>(name: T) -> Summary {
@@ -584,7 +588,7 @@ pub fn pkg_dep<T: ToPkgId>(name: T, dep: Vec<Dependency>) -> Summary {
dep,
&BTreeMap::new(),
link,
- None::<&String>,
+ None::<RustVersion>,
)
.unwrap()
}
@@ -612,7 +616,7 @@ pub fn pkg_loc(name: &str, loc: &str) -> Summary {
Vec::new(),
&BTreeMap::new(),
link,
- None::<&String>,
+ None::<RustVersion>,
)
.unwrap()
}
@@ -626,7 +630,7 @@ pub fn remove_dep(sum: &Summary, ind: usize) -> Summary {
deps,
&BTreeMap::new(),
sum.links().map(|a| a.as_str()),
- None::<&String>,
+ None::<RustVersion>,
)
.unwrap()
}
diff --git a/src/tools/cargo/crates/resolver-tests/tests/resolve.rs b/src/tools/cargo/crates/resolver-tests/tests/resolve.rs
index 02486bfb5..dd21502d8 100644
--- a/src/tools/cargo/crates/resolver-tests/tests/resolve.rs
+++ b/src/tools/cargo/crates/resolver-tests/tests/resolve.rs
@@ -1562,3 +1562,36 @@ package `A v0.0.0 (registry `https://example.com/`)`
... which satisfies dependency `C = \"*\"` of package `A v0.0.0 (registry `https://example.com/`)`\
", error.to_string());
}
+
+#[test]
+fn shortest_path_in_error_message() {
+ let input = vec![
+ pkg!(("F", "0.1.2")),
+ pkg!(("F", "0.1.1") => [dep("bad"),]),
+ pkg!(("F", "0.1.0") => [dep("bad"),]),
+ pkg!("E" => [dep_req("F", "^0.1.2"),]),
+ pkg!("D" => [dep_req("F", "^0.1.2"),]),
+ pkg!("C" => [dep("D"),]),
+ pkg!("A" => [dep("C"),dep("E"),dep_req("F", "<=0.1.1"),]),
+ ];
+ let error = resolve(vec![dep("A")], &registry(input)).unwrap_err();
+ println!("{}", error);
+ assert_eq!(
+ "\
+failed to select a version for `F`.
+ ... required by package `A v1.0.0 (registry `https://example.com/`)`
+ ... which satisfies dependency `A = \"*\"` of package `root v1.0.0 (registry `https://example.com/`)`
+versions that meet the requirements `<=0.1.1` are: 0.1.1, 0.1.0
+
+all possible versions conflict with previously selected packages.
+
+ previously selected package `F v0.1.2 (registry `https://example.com/`)`
+ ... which satisfies dependency `F = \"^0.1.2\"` of package `E v1.0.0 (registry `https://example.com/`)`
+ ... which satisfies dependency `E = \"*\"` of package `A v1.0.0 (registry `https://example.com/`)`
+ ... which satisfies dependency `A = \"*\"` of package `root v1.0.0 (registry `https://example.com/`)`
+
+failed to select a version for `F` which could resolve this conflict\
+ ",
+ error.to_string()
+ );
+}
diff --git a/src/tools/cargo/crates/semver-check/Cargo.toml b/src/tools/cargo/crates/semver-check/Cargo.toml
index 17e696566..7387c3091 100644
--- a/src/tools/cargo/crates/semver-check/Cargo.toml
+++ b/src/tools/cargo/crates/semver-check/Cargo.toml
@@ -2,6 +2,7 @@
name = "semver-check"
version = "0.0.0"
authors = ["Eric Huss"]
+rust-version.workspace = true
edition.workspace = true
publish = false
diff --git a/src/tools/cargo/crates/semver-check/src/main.rs b/src/tools/cargo/crates/semver-check/src/main.rs
index 1ba405f57..9ea0d1244 100644
--- a/src/tools/cargo/crates/semver-check/src/main.rs
+++ b/src/tools/cargo/crates/semver-check/src/main.rs
@@ -20,7 +20,7 @@ use std::process::{Command, Output};
fn main() {
if let Err(e) = doit() {
- println!("error: {}", e);
+ eprintln!("error: {}", e);
std::process::exit(1);
}
}
@@ -103,7 +103,7 @@ fn doit() -> Result<(), Box<dyn Error>> {
result
};
let expect_success = parts[0][0].contains("MINOR");
- println!("Running test from line {}", block_start);
+ eprintln!("Running test from line {}", block_start);
let result = run_test(
join(parts[1]),
diff --git a/src/tools/cargo/crates/xtask-build-man/Cargo.toml b/src/tools/cargo/crates/xtask-build-man/Cargo.toml
index bec10c48c..9e92125a1 100644
--- a/src/tools/cargo/crates/xtask-build-man/Cargo.toml
+++ b/src/tools/cargo/crates/xtask-build-man/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "xtask-build-man"
version = "0.0.0"
+rust-version.workspace = true
edition.workspace = true
publish = false
diff --git a/src/tools/cargo/crates/xtask-bump-check/Cargo.toml b/src/tools/cargo/crates/xtask-bump-check/Cargo.toml
index e965ad09e..e878f7dda 100644
--- a/src/tools/cargo/crates/xtask-bump-check/Cargo.toml
+++ b/src/tools/cargo/crates/xtask-bump-check/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "xtask-bump-check"
version = "0.0.0"
+rust-version.workspace = true
edition.workspace = true
publish = false
diff --git a/src/tools/cargo/crates/xtask-bump-check/src/main.rs b/src/tools/cargo/crates/xtask-bump-check/src/main.rs
index 0461ab91a..11242696f 100644
--- a/src/tools/cargo/crates/xtask-bump-check/src/main.rs
+++ b/src/tools/cargo/crates/xtask-bump-check/src/main.rs
@@ -20,6 +20,7 @@ fn setup_logger() {
let env = tracing_subscriber::EnvFilter::from_env("CARGO_LOG");
tracing_subscriber::fmt()
+ .with_timer(tracing_subscriber::fmt::time::Uptime::default())
.with_ansi(std::io::IsTerminal::is_terminal(&std::io::stderr()))
.with_writer(std::io::stderr)
.with_env_filter(env)
diff --git a/src/tools/cargo/crates/xtask-bump-check/src/xtask.rs b/src/tools/cargo/crates/xtask-bump-check/src/xtask.rs
index f89152331..4bf3f03d5 100644
--- a/src/tools/cargo/crates/xtask-bump-check/src/xtask.rs
+++ b/src/tools/cargo/crates/xtask-bump-check/src/xtask.rs
@@ -18,10 +18,10 @@ use std::task;
use cargo::core::dependency::Dependency;
use cargo::core::registry::PackageRegistry;
use cargo::core::Package;
-use cargo::core::QueryKind;
use cargo::core::Registry;
use cargo::core::SourceId;
use cargo::core::Workspace;
+use cargo::sources::source::QueryKind;
use cargo::util::command_prelude::*;
use cargo::util::ToSemver;
use cargo::CargoResult;
@@ -105,7 +105,7 @@ fn config_configure(config: &mut Config, args: &ArgMatches) -> CliResult {
/// Main entry of `xtask-bump-check`.
///
/// Assumption: version number are incremental. We never have point release for old versions.
-fn bump_check(args: &clap::ArgMatches, config: &mut cargo::util::Config) -> CargoResult<()> {
+fn bump_check(args: &clap::ArgMatches, config: &cargo::util::Config) -> CargoResult<()> {
let ws = args.workspace(config)?;
let repo = git2::Repository::open(ws.root())?;
let base_commit = get_base_commit(config, args, &repo)?;
@@ -161,7 +161,7 @@ fn bump_check(args: &clap::ArgMatches, config: &mut cargo::util::Config) -> Carg
];
// Even when we test against baseline-rev, we still need to make sure a
- // change doesn't violate SemVer rules aginst crates.io releases. The
+ // change doesn't violate SemVer rules against crates.io releases. The
// possibility of this happening is nearly zero but no harm to check twice.
let mut cmd = ProcessBuilder::new("cargo");
cmd.arg("semver-checks")
@@ -184,7 +184,7 @@ fn bump_check(args: &clap::ArgMatches, config: &mut cargo::util::Config) -> Carg
status("no version bump needed for member crates.")?;
- return Ok(());
+ Ok(())
}
/// Returns the commit of upstream `master` branch if `base-rev` is missing.
@@ -256,7 +256,7 @@ fn get_referenced_commit<'a>(
repo: &'a git2::Repository,
base: &git2::Commit<'a>,
) -> CargoResult<Option<git2::Commit<'a>>> {
- let [beta, stable] = beta_and_stable_branch(&repo)?;
+ let [beta, stable] = beta_and_stable_branch(repo)?;
let rev_id = base.id();
let stable_commit = stable.get().peel_to_commit()?;
let beta_commit = beta.get().peel_to_commit()?;
@@ -397,7 +397,7 @@ fn check_crates_io<'a>(
Ok(())
}
-/// Checkouts a temporary workspace to do further version comparsions.
+/// Checkouts a temporary workspace to do further version comparisons.
fn checkout_ws<'cfg, 'a>(
ws: &Workspace<'cfg>,
repo: &'a git2::Repository,
diff --git a/src/tools/cargo/crates/xtask-stale-label/Cargo.toml b/src/tools/cargo/crates/xtask-stale-label/Cargo.toml
index b1f54a2f1..8d68536d2 100644
--- a/src/tools/cargo/crates/xtask-stale-label/Cargo.toml
+++ b/src/tools/cargo/crates/xtask-stale-label/Cargo.toml
@@ -1,6 +1,7 @@
[package]
name = "xtask-stale-label"
version = "0.0.0"
+rust-version.workspace = true
edition.workspace = true
publish = false
diff --git a/src/tools/cargo/credential/cargo-credential-1password/Cargo.toml b/src/tools/cargo/credential/cargo-credential-1password/Cargo.toml
index a607e6da1..d7bd949d1 100644
--- a/src/tools/cargo/credential/cargo-credential-1password/Cargo.toml
+++ b/src/tools/cargo/credential/cargo-credential-1password/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "cargo-credential-1password"
-version = "0.3.0"
+version = "0.4.0"
edition.workspace = true
license.workspace = true
repository = "https://github.com/rust-lang/cargo"
diff --git a/src/tools/cargo/credential/cargo-credential-1password/README.md b/src/tools/cargo/credential/cargo-credential-1password/README.md
index 7cc15e05b..3648efe4b 100644
--- a/src/tools/cargo/credential/cargo-credential-1password/README.md
+++ b/src/tools/cargo/credential/cargo-credential-1password/README.md
@@ -1,7 +1,18 @@
# cargo-credential-1password
-This is the implementation for the Cargo credential helper for [1password].
-See the [credential-process] documentation for how to use this.
+A Cargo [credential provider] for [1password].
+
+`cargo-credential-1password` uses the 1password `op` CLI to store the token. You must
+install the `op` CLI from the [1password
+website](https://1password.com/downloads/command-line/). You must run `op signin`
+at least once with the appropriate arguments (such as `op signin my.1password.com user@example.com`),
+unless you provide the sign-in-address and email arguments. The master password will be required on each request
+unless the appropriate `OP_SESSION` environment variable is set. It supports
+the following command-line arguments:
+* `--account`: The account shorthand name to use.
+* `--vault`: The vault name to use.
+* `--sign-in-address`: The sign-in-address, which is a web address such as `my.1password.com`.
+* `--email`: The email address to sign in with.
[1password]: https://1password.com/
-[credential-process]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#credential-process
+[credential provider]: https://doc.rust-lang.org/nightly/cargo/reference/registry-authentication.html
diff --git a/src/tools/cargo/credential/cargo-credential-1password/src/main.rs b/src/tools/cargo/credential/cargo-credential-1password/src/main.rs
index a2607fd2f..921b52145 100644
--- a/src/tools/cargo/credential/cargo-credential-1password/src/main.rs
+++ b/src/tools/cargo/credential/cargo-credential-1password/src/main.rs
@@ -255,8 +255,8 @@ pub struct OnePasswordCredential {}
impl Credential for OnePasswordCredential {
fn perform(
&self,
- registry: &RegistryInfo,
- action: &Action,
+ registry: &RegistryInfo<'_>,
+ action: &Action<'_>,
args: &[&str],
) -> Result<CredentialResponse, Error> {
let op = OnePasswordKeychain::new(args)?;
diff --git a/src/tools/cargo/credential/cargo-credential-libsecret/Cargo.toml b/src/tools/cargo/credential/cargo-credential-libsecret/Cargo.toml
index 1bd4bb7d0..5bedad3b9 100644
--- a/src/tools/cargo/credential/cargo-credential-libsecret/Cargo.toml
+++ b/src/tools/cargo/credential/cargo-credential-libsecret/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "cargo-credential-libsecret"
-version = "0.3.1"
+version = "0.3.2"
edition.workspace = true
license.workspace = true
repository = "https://github.com/rust-lang/cargo"
diff --git a/src/tools/cargo/credential/cargo-credential-libsecret/README.md b/src/tools/cargo/credential/cargo-credential-libsecret/README.md
index f169323e0..aaba2887f 100644
--- a/src/tools/cargo/credential/cargo-credential-libsecret/README.md
+++ b/src/tools/cargo/credential/cargo-credential-libsecret/README.md
@@ -1,7 +1,9 @@
# cargo-credential-libsecret
This is the implementation for the Cargo credential helper for [GNOME libsecret].
-See the [credential-process] documentation for how to use this.
+See the [credential-provider] documentation for how to use this.
+
+This credential provider is built-in to cargo as `cargo:libsecret`.
[GNOME libsecret]: https://wiki.gnome.org/Projects/Libsecret
-[credential-process]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#credential-process
+[credential-provider]: https://doc.rust-lang.org/nightly/cargo/reference/registry-authentication.html
diff --git a/src/tools/cargo/credential/cargo-credential-libsecret/src/lib.rs b/src/tools/cargo/credential/cargo-credential-libsecret/src/lib.rs
index f83b424ee..ee1797605 100644
--- a/src/tools/cargo/credential/cargo-credential-libsecret/src/lib.rs
+++ b/src/tools/cargo/credential/cargo-credential-libsecret/src/lib.rs
@@ -104,16 +104,16 @@ mod linux {
impl Credential for LibSecretCredential {
fn perform(
&self,
- registry: &RegistryInfo,
- action: &Action,
+ registry: &RegistryInfo<'_>,
+ action: &Action<'_>,
_args: &[&str],
) -> Result<CredentialResponse, Error> {
// Dynamically load libsecret to avoid users needing to install
// additional -dev packages when building this provider.
let lib;
- let secret_password_lookup_sync: Symbol<SecretPasswordLookupSync>;
- let secret_password_store_sync: Symbol<SecretPasswordStoreSync>;
- let secret_password_clear_sync: Symbol<SecretPasswordClearSync>;
+ let secret_password_lookup_sync: Symbol<'_, SecretPasswordLookupSync>;
+ let secret_password_store_sync: Symbol<'_, SecretPasswordStoreSync>;
+ let secret_password_clear_sync: Symbol<'_, SecretPasswordClearSync>;
unsafe {
lib = Library::new("libsecret-1.so").context(
"failed to load libsecret: try installing the `libsecret` \
diff --git a/src/tools/cargo/credential/cargo-credential-macos-keychain/Cargo.toml b/src/tools/cargo/credential/cargo-credential-macos-keychain/Cargo.toml
index 342c771b5..172e9c10b 100644
--- a/src/tools/cargo/credential/cargo-credential-macos-keychain/Cargo.toml
+++ b/src/tools/cargo/credential/cargo-credential-macos-keychain/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "cargo-credential-macos-keychain"
-version = "0.3.0"
+version = "0.3.1"
edition.workspace = true
license.workspace = true
repository = "https://github.com/rust-lang/cargo"
diff --git a/src/tools/cargo/credential/cargo-credential-macos-keychain/README.md b/src/tools/cargo/credential/cargo-credential-macos-keychain/README.md
index 554116b55..f5efe496b 100644
--- a/src/tools/cargo/credential/cargo-credential-macos-keychain/README.md
+++ b/src/tools/cargo/credential/cargo-credential-macos-keychain/README.md
@@ -1,7 +1,10 @@
# cargo-credential-macos-keychain
This is the implementation for the Cargo credential helper for [macOS Keychain].
-See the [credential-process] documentation for how to use this.
+See the [credential-provider] documentation for how to use this.
+
+This credential provider is built-in to cargo as `cargo:macos-keychain`.
[macOS Keychain]: https://support.apple.com/guide/keychain-access/welcome/mac
-[credential-process]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#credential-process
+[credential-provider]: https://doc.rust-lang.org/nightly/cargo/reference/registry-authentication.html
+
diff --git a/src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml b/src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml
index 8c609dc4e..6da6578a5 100644
--- a/src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml
+++ b/src/tools/cargo/credential/cargo-credential-wincred/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "cargo-credential-wincred"
-version = "0.3.0"
+version = "0.3.1"
edition.workspace = true
license.workspace = true
repository = "https://github.com/rust-lang/cargo"
diff --git a/src/tools/cargo/credential/cargo-credential-wincred/README.md b/src/tools/cargo/credential/cargo-credential-wincred/README.md
index 8c8d18789..1995e9d76 100644
--- a/src/tools/cargo/credential/cargo-credential-wincred/README.md
+++ b/src/tools/cargo/credential/cargo-credential-wincred/README.md
@@ -1,7 +1,9 @@
# cargo-credential-wincred
This is the implementation for the Cargo credential helper for [Windows Credential Manager].
-See the [credential-process] documentation for how to use this.
+See the [credential-provider] documentation for how to use this.
+
+This credential provider is built-in to cargo as `cargo:wincred`.
[Windows Credential Manager]: https://support.microsoft.com/en-us/windows/accessing-credential-manager-1b5c916a-6a16-889f-8581-fc16e8165ac0
-[credential-process]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#credential-process
+[credential-provider]: https://doc.rust-lang.org/nightly/cargo/reference/registry-authentication.html
diff --git a/src/tools/cargo/credential/cargo-credential-wincred/src/lib.rs b/src/tools/cargo/credential/cargo-credential-wincred/src/lib.rs
index 9200ca58f..24b072ee2 100644
--- a/src/tools/cargo/credential/cargo-credential-wincred/src/lib.rs
+++ b/src/tools/cargo/credential/cargo-credential-wincred/src/lib.rs
@@ -38,8 +38,8 @@ mod win {
impl Credential for WindowsCredential {
fn perform(
&self,
- registry: &RegistryInfo,
- action: &Action,
+ registry: &RegistryInfo<'_>,
+ action: &Action<'_>,
_args: &[&str],
) -> Result<CredentialResponse, Error> {
match action {
diff --git a/src/tools/cargo/credential/cargo-credential/Cargo.toml b/src/tools/cargo/credential/cargo-credential/Cargo.toml
index 8cd1348be..c8db996bf 100644
--- a/src/tools/cargo/credential/cargo-credential/Cargo.toml
+++ b/src/tools/cargo/credential/cargo-credential/Cargo.toml
@@ -1,8 +1,9 @@
[package]
name = "cargo-credential"
-version = "0.3.0"
+version = "0.4.0"
edition.workspace = true
license.workspace = true
+rust-version = "1.70.0"
repository = "https://github.com/rust-lang/cargo"
description = "A library to assist writing Cargo credential helpers."
diff --git a/src/tools/cargo/credential/cargo-credential/README.md b/src/tools/cargo/credential/cargo-credential/README.md
index 049b3ba55..d87d41bb8 100644
--- a/src/tools/cargo/credential/cargo-credential/README.md
+++ b/src/tools/cargo/credential/cargo-credential/README.md
@@ -5,7 +5,7 @@ provides an interface to store tokens for authorizing access to a registry
such as https://crates.io/.
Documentation about credential processes may be found at
-https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#credential-process
+https://doc.rust-lang.org/nightly/cargo/reference/credential-provider-protocol.html
Example implementations may be found at
https://github.com/rust-lang/cargo/tree/master/credential
@@ -18,7 +18,7 @@ Create a Cargo project with this as a dependency:
# Add this to your Cargo.toml:
[dependencies]
-cargo-credential = "0.3"
+cargo-credential = "0.4"
```
And then include a `main.rs` binary which implements the `Credential` trait, and calls
diff --git a/src/tools/cargo/credential/cargo-credential/examples/file-provider.rs b/src/tools/cargo/credential/cargo-credential/examples/file-provider.rs
index d11958536..3ed312cb8 100644
--- a/src/tools/cargo/credential/cargo-credential/examples/file-provider.rs
+++ b/src/tools/cargo/credential/cargo-credential/examples/file-provider.rs
@@ -12,8 +12,8 @@ struct FileCredential;
impl Credential for FileCredential {
fn perform(
&self,
- registry: &RegistryInfo,
- action: &Action,
+ registry: &RegistryInfo<'_>,
+ action: &Action<'_>,
_args: &[&str],
) -> Result<CredentialResponse, cargo_credential::Error> {
if registry.index_url != "https://github.com/rust-lang/crates.io-index" {
diff --git a/src/tools/cargo/credential/cargo-credential/examples/stdout-redirected.rs b/src/tools/cargo/credential/cargo-credential/examples/stdout-redirected.rs
index 0b9bcc2f7..75a2d16d1 100644
--- a/src/tools/cargo/credential/cargo-credential/examples/stdout-redirected.rs
+++ b/src/tools/cargo/credential/cargo-credential/examples/stdout-redirected.rs
@@ -7,8 +7,8 @@ struct MyCredential;
impl Credential for MyCredential {
fn perform(
&self,
- _registry: &RegistryInfo,
- _action: &Action,
+ _registry: &RegistryInfo<'_>,
+ _action: &Action<'_>,
_args: &[&str],
) -> Result<CredentialResponse, Error> {
// Informational messages should be sent on stderr.
diff --git a/src/tools/cargo/credential/cargo-credential/src/error.rs b/src/tools/cargo/credential/cargo-credential/src/error.rs
index 2ebaf9977..8c5fe19e5 100644
--- a/src/tools/cargo/credential/cargo-credential/src/error.rs
+++ b/src/tools/cargo/credential/cargo-credential/src/error.rs
@@ -42,9 +42,9 @@ pub enum Error {
}
impl From<String> for Error {
- fn from(err: String) -> Self {
+ fn from(message: String) -> Self {
Box::new(StringTypedError {
- message: err.to_string(),
+ message,
source: None,
})
.into()
diff --git a/src/tools/cargo/credential/cargo-credential/src/lib.rs b/src/tools/cargo/credential/cargo-credential/src/lib.rs
index 0fb495ed3..60bce65be 100644
--- a/src/tools/cargo/credential/cargo-credential/src/lib.rs
+++ b/src/tools/cargo/credential/cargo-credential/src/lib.rs
@@ -50,7 +50,7 @@ pub use secret::Secret;
use stdio::stdin_stdout_to_console;
/// Message sent by the credential helper on startup
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct CredentialHello {
// Protocol versions supported by the credential process.
pub v: Vec<u32>,
@@ -61,8 +61,8 @@ pub struct UnsupportedCredential;
impl Credential for UnsupportedCredential {
fn perform(
&self,
- _registry: &RegistryInfo,
- _action: &Action,
+ _registry: &RegistryInfo<'_>,
+ _action: &Action<'_>,
_args: &[&str],
) -> Result<CredentialResponse, Error> {
Err(Error::UrlNotSupported)
@@ -70,7 +70,7 @@ impl Credential for UnsupportedCredential {
}
/// Message sent by Cargo to the credential helper after the hello
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub struct CredentialRequest<'a> {
// Cargo will respond with the highest common protocol supported by both.
@@ -80,23 +80,25 @@ pub struct CredentialRequest<'a> {
#[serde(borrow, flatten)]
pub action: Action<'a>,
/// Additional command-line arguments passed to the credential provider.
+ #[serde(skip_serializing_if = "Vec::is_empty", default)]
pub args: Vec<&'a str>,
}
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub struct RegistryInfo<'a> {
/// Registry index url
pub index_url: &'a str,
/// Name of the registry in configuration. May not be available.
/// The crates.io registry will be `crates-io` (`CRATES_IO_REGISTRY`).
+ #[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<&'a str>,
/// Headers from attempting to access a registry that resulted in a HTTP 401.
#[serde(skip_serializing_if = "Vec::is_empty", default)]
pub headers: Vec<String>,
}
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
#[serde(tag = "kind", rename_all = "kebab-case")]
pub enum Action<'a> {
@@ -119,17 +121,19 @@ impl<'a> Display for Action<'a> {
}
}
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub struct LoginOptions<'a> {
/// Token passed on the command line via --token or from stdin
+ #[serde(skip_serializing_if = "Option::is_none")]
pub token: Option<Secret<&'a str>>,
/// Optional URL that the user can visit to log in to the registry
+ #[serde(skip_serializing_if = "Option::is_none")]
pub login_url: Option<&'a str>,
}
/// A record of what kind of operation is happening that we should generate a token for.
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
#[serde(tag = "operation", rename_all = "kebab-case")]
pub enum Operation<'a> {
@@ -168,12 +172,13 @@ pub enum Operation<'a> {
}
/// Message sent by the credential helper
-#[derive(Serialize, Deserialize, Clone, Debug)]
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(tag = "kind", rename_all = "kebab-case")]
#[non_exhaustive]
pub enum CredentialResponse {
Get {
token: Secret<String>,
+ #[serde(flatten)]
cache: CacheControl,
operation_independent: bool,
},
@@ -183,30 +188,35 @@ pub enum CredentialResponse {
Unknown,
}
-#[derive(Serialize, Deserialize, Clone, Debug)]
-#[serde(rename_all = "kebab-case")]
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
+#[serde(tag = "cache", rename_all = "kebab-case")]
#[non_exhaustive]
pub enum CacheControl {
/// Do not cache this result.
Never,
/// Cache this result and use it for subsequent requests in the current Cargo invocation until the specified time.
- Expires(#[serde(with = "time::serde::timestamp")] OffsetDateTime),
+ Expires {
+ #[serde(with = "time::serde::timestamp")]
+ expiration: OffsetDateTime,
+ },
/// Cache this result and use it for all subsequent requests in the current Cargo invocation.
Session,
#[serde(other)]
Unknown,
}
-/// Credential process JSON protocol version. Incrementing
-/// this version will prevent new credential providers
-/// from working with older versions of Cargo.
+/// Credential process JSON protocol version. If the protocol needs to make
+/// a breaking change, a new protocol version should be defined (`PROTOCOL_VERSION_2`).
+/// This library should offer support for both protocols if possible, by signaling
+/// in the `CredentialHello` message. Cargo will then choose which protocol to use,
+/// or it will error if there are no common protocol versions available.
pub const PROTOCOL_VERSION_1: u32 = 1;
pub trait Credential {
/// Retrieves a token for the given registry.
fn perform(
&self,
- registry: &RegistryInfo,
- action: &Action,
+ registry: &RegistryInfo<'_>,
+ action: &Action<'_>,
args: &[&str],
) -> Result<CredentialResponse, Error>;
}
@@ -236,11 +246,7 @@ fn doit(
if len == 0 {
return Ok(());
}
- let request: CredentialRequest = serde_json::from_str(&buffer)?;
- if request.v != PROTOCOL_VERSION_1 {
- return Err(format!("unsupported protocol version {}", request.v).into());
- }
-
+ let request = deserialize_request(&buffer)?;
let response = stdin_stdout_to_console(|| {
credential.perform(&request.registry, &request.action, &request.args)
})?;
@@ -250,6 +256,17 @@ fn doit(
}
}
+/// Deserialize a request from Cargo.
+fn deserialize_request(
+ value: &str,
+) -> Result<CredentialRequest<'_>, Box<dyn std::error::Error + Send + Sync>> {
+ let request: CredentialRequest<'_> = serde_json::from_str(&value)?;
+ if request.v != PROTOCOL_VERSION_1 {
+ return Err(format!("unsupported protocol version {}", request.v).into());
+ }
+ Ok(request)
+}
+
/// Read a line of text from stdin.
pub fn read_line() -> Result<String, io::Error> {
let mut buf = String::new();
@@ -259,8 +276,8 @@ pub fn read_line() -> Result<String, io::Error> {
/// Prompt the user for a token.
pub fn read_token(
- login_options: &LoginOptions,
- registry: &RegistryInfo,
+ login_options: &LoginOptions<'_>,
+ registry: &RegistryInfo<'_>,
) -> Result<Secret<String>, Error> {
if let Some(token) = &login_options.token {
return Ok(token.to_owned());
@@ -276,3 +293,142 @@ pub fn read_token(
Ok(Secret::from(read_line().map_err(Box::new)?))
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn unsupported_version() {
+ // This shouldn't ever happen in practice, since the credential provider signals to Cargo which
+ // protocol versions it supports, and Cargo should only attempt to use one of those.
+ let msg = r#"{"v":999, "registry": {"index-url":""}, "args":[], "kind": "unexpected"}"#;
+ assert_eq!(
+ "unsupported protocol version 999",
+ deserialize_request(msg).unwrap_err().to_string()
+ );
+ }
+
+ #[test]
+ fn cache_control() {
+ let cc = CacheControl::Expires {
+ expiration: OffsetDateTime::from_unix_timestamp(1693928537).unwrap(),
+ };
+ let json = serde_json::to_string(&cc).unwrap();
+ assert_eq!(json, r#"{"cache":"expires","expiration":1693928537}"#);
+
+ let cc = CacheControl::Session;
+ let json = serde_json::to_string(&cc).unwrap();
+ assert_eq!(json, r#"{"cache":"session"}"#);
+
+ let cc: CacheControl = serde_json::from_str(r#"{"cache":"unknown-kind"}"#).unwrap();
+ assert_eq!(cc, CacheControl::Unknown);
+
+ assert_eq!(
+ "missing field `expiration`",
+ serde_json::from_str::<CacheControl>(r#"{"cache":"expires"}"#)
+ .unwrap_err()
+ .to_string()
+ );
+ }
+
+ #[test]
+ fn credential_response() {
+ let cr = CredentialResponse::Get {
+ cache: CacheControl::Never,
+ operation_independent: true,
+ token: Secret::from("value".to_string()),
+ };
+ let json = serde_json::to_string(&cr).unwrap();
+ assert_eq!(
+ json,
+ r#"{"kind":"get","token":"value","cache":"never","operation_independent":true}"#
+ );
+
+ let cr = CredentialResponse::Login;
+ let json = serde_json::to_string(&cr).unwrap();
+ assert_eq!(json, r#"{"kind":"login"}"#);
+
+ let cr: CredentialResponse =
+ serde_json::from_str(r#"{"kind":"unknown-kind","extra-data":true}"#).unwrap();
+ assert_eq!(cr, CredentialResponse::Unknown);
+
+ let cr: CredentialResponse =
+ serde_json::from_str(r#"{"kind":"login","extra-data":true}"#).unwrap();
+ assert_eq!(cr, CredentialResponse::Login);
+
+ let cr: CredentialResponse = serde_json::from_str(r#"{"kind":"get","token":"value","cache":"never","operation_independent":true,"extra-field-ignored":123}"#).unwrap();
+ assert_eq!(
+ cr,
+ CredentialResponse::Get {
+ cache: CacheControl::Never,
+ operation_independent: true,
+ token: Secret::from("value".to_string())
+ }
+ );
+ }
+
+ #[test]
+ fn credential_request() {
+ let get_oweners = CredentialRequest {
+ v: PROTOCOL_VERSION_1,
+ args: vec![],
+ registry: RegistryInfo {
+ index_url: "url",
+ name: None,
+ headers: vec![],
+ },
+ action: Action::Get(Operation::Owners { name: "pkg" }),
+ };
+
+ let json = serde_json::to_string(&get_oweners).unwrap();
+ assert_eq!(
+ json,
+ r#"{"v":1,"registry":{"index-url":"url"},"kind":"get","operation":"owners","name":"pkg"}"#
+ );
+
+ let cr: CredentialRequest<'_> =
+ serde_json::from_str(r#"{"extra-1":true,"v":1,"registry":{"index-url":"url","extra-2":true},"kind":"get","operation":"owners","name":"pkg","args":[]}"#).unwrap();
+ assert_eq!(cr, get_oweners);
+ }
+
+ #[test]
+ fn credential_request_logout() {
+ let unknown = CredentialRequest {
+ v: PROTOCOL_VERSION_1,
+ args: vec![],
+ registry: RegistryInfo {
+ index_url: "url",
+ name: None,
+ headers: vec![],
+ },
+ action: Action::Logout,
+ };
+
+ let cr: CredentialRequest<'_> = serde_json::from_str(
+ r#"{"v":1,"registry":{"index-url":"url"},"kind":"logout","extra-1":true,"args":[]}"#,
+ )
+ .unwrap();
+ assert_eq!(cr, unknown);
+ }
+
+ #[test]
+ fn credential_request_unknown() {
+ let unknown = CredentialRequest {
+ v: PROTOCOL_VERSION_1,
+ args: vec![],
+ registry: RegistryInfo {
+ index_url: "",
+ name: None,
+ headers: vec![],
+ },
+ action: Action::Unknown,
+ };
+
+ let cr: CredentialRequest<'_> = serde_json::from_str(
+ r#"{"v":1,"registry":{"index-url":""},"kind":"unexpected-1","extra-1":true,"args":[]}"#,
+ )
+ .unwrap();
+ assert_eq!(cr, unknown);
+ }
+}
diff --git a/src/tools/cargo/deny.toml b/src/tools/cargo/deny.toml
index 383648171..746113f3c 100644
--- a/src/tools/cargo/deny.toml
+++ b/src/tools/cargo/deny.toml
@@ -192,11 +192,11 @@ wildcards = "allow"
# * all - Both lowest-version and simplest-path are used
highlight = "all"
# The default lint level for `default` features for crates that are members of
-# the workspace that is being checked. This can be overriden by allowing/denying
+# the workspace that is being checked. This can be overridden by allowing/denying
# `default` on a crate-by-crate basis if desired.
workspace-default-features = "allow"
# The default lint level for `default` features for external crates that are not
-# members of the workspace. This can be overriden by allowing/denying `default`
+# members of the workspace. This can be overridden by allowing/denying `default`
# on a crate-by-crate basis if desired.
external-default-features = "allow"
# List of crates that are allowed. Use with care!
diff --git a/src/tools/cargo/publish.py b/src/tools/cargo/publish.py
index 13077a69b..87ea0e896 100755
--- a/src/tools/cargo/publish.py
+++ b/src/tools/cargo/publish.py
@@ -11,12 +11,16 @@
import os
import re
import subprocess
-import time
import urllib.request
from urllib.error import HTTPError
TO_PUBLISH = [
+ 'credential/cargo-credential',
+ 'credential/cargo-credential-libsecret',
+ 'credential/cargo-credential-wincred',
+ 'credential/cargo-credential-1password',
+ 'credential/cargo-credential-macos-keychain',
'crates/cargo-platform',
'crates/cargo-util',
'crates/crates-io',
@@ -47,13 +51,9 @@ def maybe_publish(path):
def main():
print('Starting publish...')
- for i, path in enumerate(TO_PUBLISH):
- if maybe_publish(path):
- if i < len(TO_PUBLISH)-1:
- # Sleep to allow the index to update. This should probably
- # check that the index is updated, or use a retry loop
- # instead.
- time.sleep(5)
+ for path in TO_PUBLISH:
+ maybe_publish(path)
+
print('Publish complete!')
diff --git a/src/tools/cargo/src/bin/cargo/cli.rs b/src/tools/cargo/src/bin/cargo/cli.rs
index eb337d681..06b4a20e2 100644
--- a/src/tools/cargo/src/bin/cargo/cli.rs
+++ b/src/tools/cargo/src/bin/cargo/cli.rs
@@ -12,7 +12,9 @@ use std::fmt::Write;
use super::commands;
use super::list_commands;
use crate::command_prelude::*;
+use crate::util::is_rustup;
use cargo::core::features::HIDDEN;
+use cargo::util::style;
pub fn main(config: &mut LazyConfig) -> CliResult {
let args = cli().try_get_matches()?;
@@ -312,7 +314,7 @@ For more information, see issue #10049 <https://github.com/rust-lang/cargo/issue
} else {
config.shell().warn(format_args!(
"\
-user-defined alias `{cmd}` has the appearance of a manfiest-command
+user-defined alias `{cmd}` has the appearance of a manifest-command
This was previously accepted but will be phased out when `-Zscript` is stabilized.
For more information, see issue #12207 <https://github.com/rust-lang/cargo/issues/12207>."
))?;
@@ -447,7 +449,7 @@ impl Exec {
if !config.cli_unstable().script && ext_path.is_some() {
config.shell().warn(format_args!(
"\
-external subcommand `{cmd}` has the appearance of a manfiest-command
+external subcommand `{cmd}` has the appearance of a manifest-command
This was previously accepted but will be phased out when `-Zscript` is stabilized.
For more information, see issue #12207 <https://github.com/rust-lang/cargo/issues/12207>.",
))?;
@@ -511,15 +513,23 @@ impl GlobalArgs {
}
pub fn cli() -> Command {
- // ALLOWED: `RUSTUP_HOME` should only be read from process env, otherwise
- // other tools may point to executables from incompatible distributions.
- #[allow(clippy::disallowed_methods)]
- let is_rustup = std::env::var_os("RUSTUP_HOME").is_some();
- let usage = if is_rustup {
- "cargo [+toolchain] [OPTIONS] [COMMAND]\n cargo [+toolchain] [OPTIONS] -Zscript <MANIFEST_RS> [ARGS]..."
+ let usage = if is_rustup() {
+ color_print::cstr!("<cyan,bold>cargo</> <cyan>[+toolchain] [OPTIONS] [COMMAND]</>\n <cyan,bold>cargo</> <cyan>[+toolchain] [OPTIONS]</> <cyan,bold>-Zscript</> <cyan><<MANIFEST_RS>> [ARGS]...</>")
} else {
- "cargo [OPTIONS] [COMMAND]\n cargo [OPTIONS] -Zscript <MANIFEST_RS> [ARGS]..."
+ color_print::cstr!("<cyan,bold>cargo</> <cyan>[OPTIONS] [COMMAND]</>\n <cyan,bold>cargo</> <cyan>[OPTIONS]</> <cyan,bold>-Zscript</> <cyan><<MANIFEST_RS>> [ARGS]...</>")
};
+
+ let styles = {
+ clap::builder::styling::Styles::styled()
+ .header(style::HEADER)
+ .usage(style::USAGE)
+ .literal(style::LITERAL)
+ .placeholder(style::PLACEHOLDER)
+ .error(style::ERROR)
+ .valid(style::VALID)
+ .invalid(style::INVALID)
+ };
+
Command::new("cargo")
// Subcommands all count their args' display order independently (from 0),
// which makes their args interspersed with global args. This puts global args last.
@@ -527,44 +537,49 @@ pub fn cli() -> Command {
// We also want these to come before auto-generated `--help`
.next_display_order(800)
.allow_external_subcommands(true)
- // Doesn't mix well with our list of common cargo commands. See clap-rs/clap#3108 for
- // opening clap up to allow us to style our help template
- .disable_colored_help(true)
+ .styles(styles)
// Provide a custom help subcommand for calling into man pages
.disable_help_subcommand(true)
.override_usage(usage)
- .help_template(
+ .help_template(color_print::cstr!(
"\
Rust's package manager
-Usage: {usage}
+<green,bold>Usage:</> {usage}
-Options:
+<green,bold>Options:</>
{options}
-Some common cargo commands are (see all commands with --list):
- build, b Compile the current package
- check, c Analyze the current package and report errors, but don't build object files
- clean Remove the target directory
- doc, d Build this package's and its dependencies' documentation
- new Create a new cargo package
- init Create a new cargo package in an existing directory
- add Add dependencies to a manifest file
- remove Remove dependencies from a manifest file
- run, r Run a binary or example of the local package
- test, t Run the tests
- bench Run the benchmarks
- update Update dependencies listed in Cargo.lock
- search Search registry for crates
- publish Package and upload this package to the registry
- install Install a Rust binary. Default location is $HOME/.cargo/bin
- uninstall Uninstall a Rust binary
-
-See 'cargo help <command>' for more information on a specific command.\n",
- )
+<green,bold>Commands:</>
+ <cyan,bold>build</>, <cyan,bold>b</> Compile the current package
+ <cyan,bold>check</>, <cyan,bold>c</> Analyze the current package and report errors, but don't build object files
+ <cyan,bold>clean</> Remove the target directory
+ <cyan,bold>doc</>, <cyan,bold>d</> Build this package's and its dependencies' documentation
+ <cyan,bold>new</> Create a new cargo package
+ <cyan,bold>init</> Create a new cargo package in an existing directory
+ <cyan,bold>add</> Add dependencies to a manifest file
+ <cyan,bold>remove</> Remove dependencies from a manifest file
+ <cyan,bold>run</>, <cyan,bold>r</> Run a binary or example of the local package
+ <cyan,bold>test</>, <cyan,bold>t</> Run the tests
+ <cyan,bold>bench</> Run the benchmarks
+ <cyan,bold>update</> Update dependencies listed in Cargo.lock
+ <cyan,bold>search</> Search registry for crates
+ <cyan,bold>publish</> Package and upload this package to the registry
+ <cyan,bold>install</> Install a Rust binary. Default location is $HOME/.cargo/bin
+ <cyan,bold>uninstall</> Uninstall a Rust binary
+ <cyan>...</> See all commands with <cyan,bold>--list</>
+
+See '<cyan,bold>cargo help</> <cyan><<command>></>' for more information on a specific command.\n",
+ ))
.arg(flag("version", "Print version info and exit").short('V'))
.arg(flag("list", "List installed commands"))
- .arg(opt("explain", "Run `rustc --explain CODE`").value_name("CODE"))
+ .arg(
+ opt(
+ "explain",
+ "Provide a detailed explanation of a rustc error message",
+ )
+ .value_name("CODE"),
+ )
.arg(
opt(
"verbose",
diff --git a/src/tools/cargo/src/bin/cargo/commands/add.rs b/src/tools/cargo/src/bin/cargo/commands/add.rs
index 56df76268..344cd2af3 100644
--- a/src/tools/cargo/src/bin/cargo/commands/add.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/add.rs
@@ -18,12 +18,12 @@ pub fn cli() -> Command {
clap::Command::new("add")
.about("Add dependencies to a Cargo.toml manifest file")
.override_usage(
- "\
- cargo add [OPTIONS] <DEP>[@<VERSION>] ...
- cargo add [OPTIONS] --path <PATH> ...
- cargo add [OPTIONS] --git <URL> ..."
- )
- .after_help("Run `cargo help add` for more detailed information.\n")
+ color_print::cstr!("\
+ <cyan,bold>cargo add</> <cyan>[OPTIONS] <<DEP>>[@<<VERSION>>] ...</>
+ <cyan,bold>cargo add</> <cyan>[OPTIONS]</> <cyan,bold>--path</> <cyan><<PATH>> ...</>
+ <cyan,bold>cargo add</> <cyan>[OPTIONS]</> <cyan,bold>--git</> <cyan><<URL>> ...</>"
+ ))
+ .after_help(color_print::cstr!("Run `<cyan,bold>cargo help add</>` for more detailed information.\n"))
.group(clap::ArgGroup::new("selected").multiple(true).required(true))
.args([
clap::Arg::new("crates")
diff --git a/src/tools/cargo/src/bin/cargo/commands/bench.rs b/src/tools/cargo/src/bin/cargo/commands/bench.rs
index bb2c193b0..1a97d84a4 100644
--- a/src/tools/cargo/src/bin/cargo/commands/bench.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/bench.rs
@@ -42,30 +42,22 @@ pub fn cli() -> Command {
"Benchmark all targets",
)
.arg_features()
- .arg_jobs_without_keep_going()
- .arg(flag("keep-going", "Use `--no-fail-fast` instead").hide(true)) // See rust-lang/cargo#11702
+ .arg_jobs()
+ .arg_unsupported_keep_going()
.arg_profile("Build artifacts with the specified profile")
.arg_target_triple("Build for the target triple")
.arg_target_dir()
.arg_unit_graph()
.arg_timings()
.arg_manifest_path()
- .after_help("Run `cargo help bench` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help bench</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let ws = args.workspace(config)?;
- if args.keep_going() {
- return Err(anyhow::format_err!(
- "\
-unexpected argument `--keep-going` found
-
- tip: to run as many benchmarks as possible without failing fast, use `--no-fail-fast`"
- )
- .into());
- }
-
let mut compile_opts = args.compile_options(
config,
CompileMode::Bench,
diff --git a/src/tools/cargo/src/bin/cargo/commands/build.rs b/src/tools/cargo/src/bin/cargo/commands/build.rs
index e25638aa0..d503f43dd 100644
--- a/src/tools/cargo/src/bin/cargo/commands/build.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/build.rs
@@ -30,8 +30,9 @@ pub fn cli() -> Command {
)
.arg_features()
.arg_release("Build artifacts in release mode, with optimizations")
+ .arg_redundant_default_mode("debug", "build", "release")
.arg_profile("Build artifacts with the specified profile")
- .arg_jobs()
+ .arg_parallel()
.arg_target_triple("Build for the target triple")
.arg_target_dir()
.arg(
@@ -46,7 +47,9 @@ pub fn cli() -> Command {
.arg_unit_graph()
.arg_timings()
.arg_manifest_path()
- .after_help("Run `cargo help build` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help build</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/check.rs b/src/tools/cargo/src/bin/cargo/commands/check.rs
index ab6f99048..a54e84cdc 100644
--- a/src/tools/cargo/src/bin/cargo/commands/check.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/check.rs
@@ -29,7 +29,7 @@ pub fn cli() -> Command {
"Check all targets",
)
.arg_features()
- .arg_jobs()
+ .arg_parallel()
.arg_release("Check artifacts in release mode, with optimizations")
.arg_profile("Check artifacts with the specified profile")
.arg_target_triple("Check for the target triple")
@@ -37,7 +37,9 @@ pub fn cli() -> Command {
.arg_unit_graph()
.arg_timings()
.arg_manifest_path()
- .after_help("Run `cargo help check` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help check</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/clean.rs b/src/tools/cargo/src/bin/cargo/commands/clean.rs
index 9fa3c8527..8596561c9 100644
--- a/src/tools/cargo/src/bin/cargo/commands/clean.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/clean.rs
@@ -14,7 +14,10 @@ pub fn cli() -> Command {
.arg_target_triple("Target triple to clean output for")
.arg_target_dir()
.arg_manifest_path()
- .after_help("Run `cargo help clean` for more detailed information.\n")
+ .arg_dry_run("Display what would be deleted without deleting anything")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help clean</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
@@ -27,10 +30,11 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let opts = CleanOptions {
config,
spec: values(args, "package"),
- targets: args.targets(),
+ targets: args.targets()?,
requested_profile: args.get_profile_name(config, "dev", ProfileChecking::Custom)?,
profile_specified: args.contains_id("profile") || args.flag("release"),
doc: args.flag("doc"),
+ dry_run: args.dry_run(),
};
ops::clean(&ws, &opts)?;
Ok(())
diff --git a/src/tools/cargo/src/bin/cargo/commands/doc.rs b/src/tools/cargo/src/bin/cargo/commands/doc.rs
index c3dfe426d..43a6ee950 100644
--- a/src/tools/cargo/src/bin/cargo/commands/doc.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/doc.rs
@@ -32,7 +32,7 @@ pub fn cli() -> Command {
"Document only the specified example",
"Document all examples",
)
- .arg_jobs()
+ .arg_parallel()
.arg_release("Build artifacts in release mode, with optimizations")
.arg_profile("Build artifacts with the specified profile")
.arg_target_triple("Build for the target triple")
@@ -40,7 +40,9 @@ pub fn cli() -> Command {
.arg_unit_graph()
.arg_timings()
.arg_manifest_path()
- .after_help("Run `cargo help doc` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help doc</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/fetch.rs b/src/tools/cargo/src/bin/cargo/commands/fetch.rs
index 4b1fcb40f..794dbf9b0 100644
--- a/src/tools/cargo/src/bin/cargo/commands/fetch.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/fetch.rs
@@ -9,7 +9,9 @@ pub fn cli() -> Command {
.arg_quiet()
.arg_target_triple("Fetch dependencies for the target triple")
.arg_manifest_path()
- .after_help("Run `cargo help fetch` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help fetch</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
@@ -17,7 +19,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let opts = FetchOptions {
config,
- targets: args.targets(),
+ targets: args.targets()?,
};
let _ = ops::fetch(&ws, &opts)?;
Ok(())
diff --git a/src/tools/cargo/src/bin/cargo/commands/fix.rs b/src/tools/cargo/src/bin/cargo/commands/fix.rs
index 1f98dd67e..0ecf47450 100644
--- a/src/tools/cargo/src/bin/cargo/commands/fix.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/fix.rs
@@ -47,14 +47,16 @@ pub fn cli() -> Command {
"Fix all targets (default)",
)
.arg_features()
- .arg_jobs()
+ .arg_parallel()
.arg_release("Fix artifacts in release mode, with optimizations")
.arg_profile("Build artifacts with the specified profile")
.arg_target_triple("Fix for the target triple")
.arg_target_dir()
.arg_timings()
.arg_manifest_path()
- .after_help("Run `cargo help fix` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help fix</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/generate_lockfile.rs b/src/tools/cargo/src/bin/cargo/commands/generate_lockfile.rs
index 7d06aad59..4f1382ee5 100644
--- a/src/tools/cargo/src/bin/cargo/commands/generate_lockfile.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/generate_lockfile.rs
@@ -7,7 +7,9 @@ pub fn cli() -> Command {
.about("Generate the lockfile for a package")
.arg_quiet()
.arg_manifest_path()
- .after_help("Run `cargo help generate-lockfile` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help generate-lockfile</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/init.rs b/src/tools/cargo/src/bin/cargo/commands/init.rs
index fdb3dc208..48409d827 100644
--- a/src/tools/cargo/src/bin/cargo/commands/init.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/init.rs
@@ -7,9 +7,11 @@ pub fn cli() -> Command {
.about("Create a new cargo package in an existing directory")
.arg(Arg::new("path").action(ArgAction::Set).default_value("."))
.arg_new_opts()
- .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
+ .arg_registry("Registry to use")
.arg_quiet()
- .after_help("Run `cargo help init` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help init</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/install.rs b/src/tools/cargo/src/bin/cargo/commands/install.rs
index 8abb00190..2e5163bdc 100644
--- a/src/tools/cargo/src/bin/cargo/commands/install.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/install.rs
@@ -1,24 +1,27 @@
use crate::command_prelude::*;
use anyhow::anyhow;
+use anyhow::bail;
+use anyhow::format_err;
use cargo::core::{GitReference, SourceId, Workspace};
use cargo::ops;
use cargo::util::IntoUrl;
+use cargo::util::ToSemver;
+use cargo::util::VersionReqExt;
+use cargo::CargoResult;
+use semver::VersionReq;
use cargo_util::paths;
pub fn cli() -> Command {
subcommand("install")
.about("Install a Rust binary. Default location is $HOME/.cargo/bin")
- .arg(
- Arg::new("crate")
- .value_parser(clap::builder::NonEmptyStringValueParser::new())
- .num_args(0..),
- )
+ .arg(Arg::new("crate").value_parser(parse_crate).num_args(0..))
.arg(
opt("version", "Specify a version to install")
.alias("vers")
.value_name("VERSION")
+ .value_parser(parse_semver_flag)
.requires("crate"),
)
.arg(
@@ -75,16 +78,19 @@ pub fn cli() -> Command {
"Install all examples",
)
.arg_features()
- .arg_jobs()
+ .arg_parallel()
.arg(flag(
"debug",
"Build in debug mode (with the 'dev' profile) instead of release mode",
))
+ .arg_redundant_default_mode("release", "install", "debug")
.arg_profile("Install artifacts with the specified profile")
.arg_target_triple("Build for the target triple")
.arg_target_dir()
.arg_timings()
- .after_help("Run `cargo help install` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help install</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
@@ -102,11 +108,12 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
// but not `Config::reload_rooted_at` which is always cwd)
let path = path.map(|p| paths::normalize_path(&p));
- let version = args.get_one::<String>("version").map(String::as_str);
+ let version = args.get_one::<VersionReq>("version");
let krates = args
- .get_many::<String>("crate")
+ .get_many::<CrateVersion>("crate")
.unwrap_or_default()
- .map(|k| resolve_crate(k, version))
+ .cloned()
+ .map(|(krate, local_version)| resolve_crate(krate, local_version, version))
.collect::<crate::CargoResult<Vec<_>>>()?;
for (crate_name, _) in krates.iter() {
@@ -117,6 +124,16 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
)
.into());
}
+
+ if let Ok(url) = crate_name.into_url() {
+ if matches!(url.scheme(), "http" | "https") {
+ return Err(anyhow!(
+ "invalid package name: `{url}`
+ Use `cargo install --git {url}` if you meant to install from a git repository."
+ )
+ .into());
+ }
+ }
}
let mut from_cwd = false;
@@ -138,10 +155,11 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
} else if krates.is_empty() {
from_cwd = true;
SourceId::for_path(config.cwd())?
- } else if let Some(index) = args.get_one::<String>("index") {
- SourceId::for_registry(&index.into_url()?)?
- } else if let Some(registry) = args.registry(config)? {
- SourceId::alt_registry(config, &registry)?
+ } else if let Some(reg_or_index) = args.registry_or_index(config)? {
+ match reg_or_index {
+ ops::RegistryOrIndex::Registry(r) => SourceId::alt_registry(config, &r)?,
+ ops::RegistryOrIndex::Index(url) => SourceId::for_registry(&url)?,
+ }
} else {
SourceId::crates_io(config)?
};
@@ -190,20 +208,86 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
Ok(())
}
-fn resolve_crate<'k>(
- mut krate: &'k str,
- mut version: Option<&'k str>,
-) -> crate::CargoResult<(&'k str, Option<&'k str>)> {
- if let Some((k, v)) = krate.split_once('@') {
- if version.is_some() {
- anyhow::bail!("cannot specify both `@{v}` and `--version`");
- }
+type CrateVersion = (String, Option<VersionReq>);
+
+fn parse_crate(krate: &str) -> crate::CargoResult<CrateVersion> {
+ let (krate, version) = if let Some((k, v)) = krate.split_once('@') {
if k.is_empty() {
// by convention, arguments starting with `@` are response files
- anyhow::bail!("missing crate name for `@{v}`");
+ anyhow::bail!("missing crate name before '@'");
}
- krate = k;
- version = Some(v);
+ let krate = k.to_owned();
+ let version = Some(parse_semver_flag(v)?);
+ (krate, version)
+ } else {
+ let krate = krate.to_owned();
+ let version = None;
+ (krate, version)
+ };
+
+ if krate.is_empty() {
+ anyhow::bail!("crate name is empty");
}
+
+ Ok((krate, version))
+}
+
+/// Parses x.y.z as if it were =x.y.z, and gives CLI-specific error messages in the case of invalid
+/// values.
+fn parse_semver_flag(v: &str) -> CargoResult<VersionReq> {
+ // If the version begins with character <, >, =, ^, ~ parse it as a
+ // version range, otherwise parse it as a specific version
+ let first = v
+ .chars()
+ .next()
+ .ok_or_else(|| format_err!("no version provided for the `--version` flag"))?;
+
+ let is_req = "<>=^~".contains(first) || v.contains('*');
+ if is_req {
+ match v.parse::<VersionReq>() {
+ Ok(v) => Ok(v),
+ Err(_) => bail!(
+ "the `--version` provided, `{}`, is \
+ not a valid semver version requirement\n\n\
+ Please have a look at \
+ https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html \
+ for the correct format",
+ v
+ ),
+ }
+ } else {
+ match v.to_semver() {
+ Ok(v) => Ok(VersionReq::exact(&v)),
+ Err(e) => {
+ let mut msg = e.to_string();
+
+ // If it is not a valid version but it is a valid version
+ // requirement, add a note to the warning
+ if v.parse::<VersionReq>().is_ok() {
+ msg.push_str(&format!(
+ "\n\n tip: if you want to specify SemVer range, \
+ add an explicit qualifier, like '^{}'",
+ v
+ ));
+ }
+ bail!(msg);
+ }
+ }
+ }
+}
+
+fn resolve_crate(
+ krate: String,
+ local_version: Option<VersionReq>,
+ version: Option<&VersionReq>,
+) -> crate::CargoResult<CrateVersion> {
+ let version = match (local_version, version) {
+ (Some(_), Some(_)) => {
+ anyhow::bail!("cannot specify both `@<VERSION>` and `--version <VERSION>`");
+ }
+ (Some(l), None) => Some(l),
+ (None, Some(g)) => Some(g.to_owned()),
+ (None, None) => None,
+ };
Ok((krate, version))
}
diff --git a/src/tools/cargo/src/bin/cargo/commands/locate_project.rs b/src/tools/cargo/src/bin/cargo/commands/locate_project.rs
index 69f015300..217bdcac9 100644
--- a/src/tools/cargo/src/bin/cargo/commands/locate_project.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/locate_project.rs
@@ -16,7 +16,9 @@ pub fn cli() -> Command {
)
.arg_quiet()
.arg_manifest_path()
- .after_help("Run `cargo help locate-project` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help locate-project</>` for more detailed information.\n"
+ ))
}
#[derive(Serialize)]
diff --git a/src/tools/cargo/src/bin/cargo/commands/login.rs b/src/tools/cargo/src/bin/cargo/commands/login.rs
index e51adaa1c..118b03310 100644
--- a/src/tools/cargo/src/bin/cargo/commands/login.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/login.rs
@@ -1,24 +1,32 @@
-use crate::command_prelude::*;
-
use cargo::ops;
+use cargo::ops::RegistryOrIndex;
+
+use crate::command_prelude::*;
pub fn cli() -> Command {
subcommand("login")
.about("Log in to a registry.")
.arg(Arg::new("token").action(ArgAction::Set))
- .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
+ .arg_registry("Registry to use")
.arg(
Arg::new("args")
- .help("Arguments for the credential provider (unstable)")
+ .help("Additional arguments for the credential provider")
.num_args(0..)
.last(true),
)
.arg_quiet()
- .after_help("Run `cargo help login` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help login</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
- let registry = args.registry(config)?;
+ let reg = args.registry_or_index(config)?;
+ assert!(
+ !matches!(reg, Some(RegistryOrIndex::Index(..))),
+ "must not be index URL"
+ );
+
let extra_args = args
.get_many::<String>("args")
.unwrap_or_default()
@@ -27,7 +35,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
ops::registry_login(
config,
args.get_one::<String>("token").map(|s| s.as_str().into()),
- registry.as_deref(),
+ reg.as_ref(),
&extra_args,
)?;
Ok(())
diff --git a/src/tools/cargo/src/bin/cargo/commands/logout.rs b/src/tools/cargo/src/bin/cargo/commands/logout.rs
index 4320240c6..e7bacca86 100644
--- a/src/tools/cargo/src/bin/cargo/commands/logout.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/logout.rs
@@ -1,16 +1,25 @@
-use crate::command_prelude::*;
use cargo::ops;
+use cargo::ops::RegistryOrIndex;
+
+use crate::command_prelude::*;
pub fn cli() -> Command {
subcommand("logout")
.about("Remove an API token from the registry locally")
- .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
+ .arg_registry("Registry to use")
.arg_quiet()
- .after_help("Run `cargo help logout` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help logout</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
- let registry = args.registry(config)?;
- ops::registry_logout(config, registry.as_deref())?;
+ let reg = args.registry_or_index(config)?;
+ assert!(
+ !matches!(reg, Some(RegistryOrIndex::Index(..))),
+ "must not be index URL"
+ );
+
+ ops::registry_logout(config, reg)?;
Ok(())
}
diff --git a/src/tools/cargo/src/bin/cargo/commands/metadata.rs b/src/tools/cargo/src/bin/cargo/commands/metadata.rs
index 54257dee3..09064de7d 100644
--- a/src/tools/cargo/src/bin/cargo/commands/metadata.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/metadata.rs
@@ -26,7 +26,9 @@ pub fn cli() -> Command {
.arg_quiet()
.arg_features()
.arg_manifest_path()
- .after_help("Run `cargo help metadata` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help metadata</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/new.rs b/src/tools/cargo/src/bin/cargo/commands/new.rs
index 6124444c0..c8d19218f 100644
--- a/src/tools/cargo/src/bin/cargo/commands/new.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/new.rs
@@ -7,9 +7,11 @@ pub fn cli() -> Command {
.about("Create a new cargo package at <path>")
.arg(Arg::new("path").action(ArgAction::Set).required(true))
.arg_new_opts()
- .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
+ .arg_registry("Registry to use")
.arg_quiet()
- .after_help("Run `cargo help new` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help new</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/owner.rs b/src/tools/cargo/src/bin/cargo/commands/owner.rs
index 223327c31..00080b829 100644
--- a/src/tools/cargo/src/bin/cargo/commands/owner.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/owner.rs
@@ -24,19 +24,20 @@ pub fn cli() -> Command {
.short('r'),
)
.arg(flag("list", "List owners of a crate").short('l'))
- .arg(opt("index", "Registry index to modify owners for").value_name("INDEX"))
+ .arg_index("Registry index URL to modify owners for")
+ .arg_registry("Registry to modify owners for")
.arg(opt("token", "API token to use when authenticating").value_name("TOKEN"))
- .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
.arg_quiet()
- .after_help("Run `cargo help owner` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help owner</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
- let registry = args.registry(config)?;
let opts = OwnersOptions {
krate: args.get_one::<String>("crate").cloned(),
token: args.get_one::<String>("token").cloned().map(Secret::from),
- index: args.get_one::<String>("index").cloned(),
+ reg_or_index: args.registry_or_index(config)?,
to_add: args
.get_many::<String>("add")
.map(|xs| xs.cloned().collect()),
@@ -44,7 +45,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
.get_many::<String>("remove")
.map(|xs| xs.cloned().collect()),
list: args.flag("list"),
- registry,
};
ops::modify_owners(config, &opts)?;
Ok(())
diff --git a/src/tools/cargo/src/bin/cargo/commands/package.rs b/src/tools/cargo/src/bin/cargo/commands/package.rs
index cf4ac795c..0020e365e 100644
--- a/src/tools/cargo/src/bin/cargo/commands/package.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/package.rs
@@ -33,9 +33,11 @@ pub fn cli() -> Command {
.arg_features()
.arg_target_triple("Build for the target triple")
.arg_target_dir()
- .arg_jobs()
+ .arg_parallel()
.arg_manifest_path()
- .after_help("Run `cargo help package` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help package</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
@@ -58,7 +60,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
check_metadata: !args.flag("no-metadata"),
allow_dirty: args.flag("allow-dirty"),
to_package: specs,
- targets: args.targets(),
+ targets: args.targets()?,
jobs: args.jobs()?,
keep_going: args.keep_going(),
cli_features: args.cli_features()?,
diff --git a/src/tools/cargo/src/bin/cargo/commands/pkgid.rs b/src/tools/cargo/src/bin/cargo/commands/pkgid.rs
index ba4540cf1..9d7a6c712 100644
--- a/src/tools/cargo/src/bin/cargo/commands/pkgid.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/pkgid.rs
@@ -10,7 +10,9 @@ pub fn cli() -> Command {
.arg_quiet()
.arg_package("Argument to get the package ID specifier for")
.arg_manifest_path()
- .after_help("Run `cargo help pkgid` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help pkgid</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/publish.rs b/src/tools/cargo/src/bin/cargo/commands/publish.rs
index bda240c8c..8ce2ffc5b 100644
--- a/src/tools/cargo/src/bin/cargo/commands/publish.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/publish.rs
@@ -6,8 +6,8 @@ pub fn cli() -> Command {
subcommand("publish")
.about("Upload a package to the registry")
.arg_dry_run("Perform all checks without uploading")
- .arg_index()
- .arg(opt("registry", "Registry to publish to").value_name("REGISTRY"))
+ .arg_index("Registry index URL to upload the package to")
+ .arg_registry("Registry to upload the package to")
.arg(opt("token", "Token to use when uploading").value_name("TOKEN"))
.arg(flag(
"no-verify",
@@ -20,15 +20,17 @@ pub fn cli() -> Command {
.arg_quiet()
.arg_package("Package to publish")
.arg_features()
- .arg_jobs()
+ .arg_parallel()
.arg_target_triple("Build for the target triple")
.arg_target_dir()
.arg_manifest_path()
- .after_help("Run `cargo help publish` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help publish</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
- let registry = args.registry(config)?;
+ let reg_or_index = args.registry_or_index(config)?;
let ws = args.workspace(config)?;
if ws.root_maybe().is_embedded() {
return Err(anyhow::format_err!(
@@ -37,7 +39,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
)
.into());
}
- let index = args.index()?;
ops::publish(
&ws,
@@ -46,15 +47,14 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
token: args
.get_one::<String>("token")
.map(|s| s.to_string().into()),
- index,
+ reg_or_index,
verify: !args.flag("no-verify"),
allow_dirty: args.flag("allow-dirty"),
to_publish: args.packages_from_flags()?,
- targets: args.targets(),
+ targets: args.targets()?,
jobs: args.jobs()?,
keep_going: args.keep_going(),
dry_run: args.dry_run(),
- registry,
cli_features: args.cli_features()?,
},
)?;
diff --git a/src/tools/cargo/src/bin/cargo/commands/read_manifest.rs b/src/tools/cargo/src/bin/cargo/commands/read_manifest.rs
index a1f42bfb0..6625d60f5 100644
--- a/src/tools/cargo/src/bin/cargo/commands/read_manifest.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/read_manifest.rs
@@ -2,13 +2,13 @@ use crate::command_prelude::*;
pub fn cli() -> Command {
subcommand("read-manifest")
- .about(
+ .about(color_print::cstr!(
"\
Print a JSON representation of a Cargo.toml manifest.
-Deprecated, use `cargo metadata --no-deps` instead.\
-",
- )
+Deprecated, use `<cyan,bold>cargo metadata --no-deps</>` instead.\
+"
+ ))
.arg_quiet()
.arg_manifest_path()
}
diff --git a/src/tools/cargo/src/bin/cargo/commands/remove.rs b/src/tools/cargo/src/bin/cargo/commands/remove.rs
index 798e6fff6..c6508a6b2 100644
--- a/src/tools/cargo/src/bin/cargo/commands/remove.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/remove.rs
@@ -50,6 +50,9 @@ pub fn cli() -> clap::Command {
])
.arg_package("Package to remove from")
.arg_manifest_path()
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help remove</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
@@ -216,7 +219,6 @@ fn gc_workspace(workspace: &Workspace<'_>) -> CargoResult<()> {
//
// Example tables:
// - profile.dev.package.foo
- // - profile.release.package."*"
// - profile.release.package."foo:2.1.0"
if let Some(toml_edit::Item::Table(profile_section_table)) = manifest.get_mut("profile") {
profile_section_table.set_implicit(true);
@@ -231,8 +233,14 @@ fn gc_workspace(workspace: &Workspace<'_>) -> CargoResult<()> {
package_table.set_implicit(true);
for (key, item) in package_table.iter_mut() {
+ let key = key.get();
+ // Skip globs. Can't do anything with them.
+ // For example, profile.release.package."*".
+ if crate::util::restricted_names::is_glob_pattern(key) {
+ continue;
+ }
if !spec_has_match(
- &PackageIdSpec::parse(key.get())?,
+ &PackageIdSpec::parse(key)?,
&dependencies,
workspace.config(),
)? {
@@ -280,7 +288,7 @@ fn spec_has_match(
}
let version_matches = match (spec.version(), dep.version()) {
- (Some(v), Some(vq)) => semver::VersionReq::parse(vq)?.matches(v),
+ (Some(v), Some(vq)) => semver::VersionReq::parse(vq)?.matches(&v),
(Some(_), None) => false,
(None, None | Some(_)) => true,
};
diff --git a/src/tools/cargo/src/bin/cargo/commands/report.rs b/src/tools/cargo/src/bin/cargo/commands/report.rs
index 275a8f7c0..bc00d5bb8 100644
--- a/src/tools/cargo/src/bin/cargo/commands/report.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/report.rs
@@ -5,7 +5,9 @@ use cargo::drop_println;
pub fn cli() -> Command {
subcommand("report")
.about("Generate and display various kinds of reports")
- .after_help("Run `cargo help report` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help report</>` for more detailed information.\n"
+ ))
.subcommand_required(true)
.arg_required_else_help(true)
.subcommand(
@@ -42,7 +44,7 @@ fn report_future_incompatibilities(config: &Config, args: &ArgMatches) -> CliRes
.value_of_u32("id")?
.unwrap_or_else(|| reports.last_id());
let krate = args.get_one::<String>("package").map(String::as_str);
- let report = reports.get_report(id, config, krate)?;
+ let report = reports.get_report(id, krate)?;
drop_println!(config, "{}", REPORT_PREAMBLE);
drop(config.shell().print_ansi_stdout(report.as_bytes()));
Ok(())
diff --git a/src/tools/cargo/src/bin/cargo/commands/run.rs b/src/tools/cargo/src/bin/cargo/commands/run.rs
index 1649f72ac..029c9ee56 100644
--- a/src/tools/cargo/src/bin/cargo/commands/run.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/run.rs
@@ -30,7 +30,7 @@ pub fn cli() -> Command {
"Name of the example target to run",
)
.arg_features()
- .arg_jobs()
+ .arg_parallel()
.arg_release("Build artifacts in release mode, with optimizations")
.arg_profile("Build artifacts with the specified profile")
.arg_target_triple("Build for the target triple")
@@ -38,7 +38,9 @@ pub fn cli() -> Command {
.arg_manifest_path()
.arg_unit_graph()
.arg_timings()
- .after_help("Run `cargo help run` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help run</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/rustc.rs b/src/tools/cargo/src/bin/cargo/commands/rustc.rs
index 0a0364e37..60f0b9d60 100644
--- a/src/tools/cargo/src/bin/cargo/commands/rustc.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/rustc.rs
@@ -44,7 +44,7 @@ pub fn cli() -> Command {
"Build all targets",
)
.arg_features()
- .arg_jobs()
+ .arg_parallel()
.arg_release("Build artifacts in release mode, with optimizations")
.arg_profile("Build artifacts with the specified profile")
.arg_target_triple("Target triple which compiles will be for")
@@ -52,7 +52,9 @@ pub fn cli() -> Command {
.arg_unit_graph()
.arg_timings()
.arg_manifest_path()
- .after_help("Run `cargo help rustc` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help rustc</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/rustdoc.rs b/src/tools/cargo/src/bin/cargo/commands/rustdoc.rs
index 488256ba7..8cb2f10de 100644
--- a/src/tools/cargo/src/bin/cargo/commands/rustdoc.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/rustdoc.rs
@@ -32,7 +32,7 @@ pub fn cli() -> Command {
"Build all targets",
)
.arg_features()
- .arg_jobs()
+ .arg_parallel()
.arg_release("Build artifacts in release mode, with optimizations")
.arg_profile("Build artifacts with the specified profile")
.arg_target_triple("Build for the target triple")
@@ -40,7 +40,9 @@ pub fn cli() -> Command {
.arg_unit_graph()
.arg_timings()
.arg_manifest_path()
- .after_help("Run `cargo help rustdoc` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help rustdoc</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/search.rs b/src/tools/cargo/src/bin/cargo/commands/search.rs
index 656172e77..9cacfc7e8 100644
--- a/src/tools/cargo/src/bin/cargo/commands/search.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/search.rs
@@ -15,15 +15,16 @@ pub fn cli() -> Command {
)
.value_name("LIMIT"),
)
- .arg_index()
- .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
+ .arg_index("Registry index URL to search packages in")
+ .arg_registry("Registry to search packages in")
.arg_quiet()
- .after_help("Run `cargo help search` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help search</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
- let registry = args.registry(config)?;
- let index = args.index()?;
+ let reg_or_index = args.registry_or_index(config)?;
let limit = args.value_of_u32("limit")?;
let limit = min(100, limit.unwrap_or(10));
let query: Vec<&str> = args
@@ -32,6 +33,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
.map(String::as_str)
.collect();
let query: String = query.join("+");
- ops::search(&query, config, index, limit, registry)?;
+ ops::search(&query, config, reg_or_index, limit)?;
Ok(())
}
diff --git a/src/tools/cargo/src/bin/cargo/commands/test.rs b/src/tools/cargo/src/bin/cargo/commands/test.rs
index 80c935d62..3c7af506d 100644
--- a/src/tools/cargo/src/bin/cargo/commands/test.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/test.rs
@@ -48,8 +48,8 @@ pub fn cli() -> Command {
"Test all targets (does not include doctests)",
)
.arg_features()
- .arg_jobs_without_keep_going()
- .arg(flag("keep-going", "Use `--no-fail-fast` instead").hide(true)) // See rust-lang/cargo#11702
+ .arg_jobs()
+ .arg_unsupported_keep_going()
.arg_release("Build artifacts in release mode, with optimizations")
.arg_profile("Build artifacts with the specified profile")
.arg_target_triple("Build for the target triple")
@@ -57,25 +57,15 @@ pub fn cli() -> Command {
.arg_unit_graph()
.arg_timings()
.arg_manifest_path()
- .after_help(
- "Run `cargo help test` for more detailed information.\n\
- Run `cargo test -- --help` for test binary options.\n",
- )
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help test</>` for more detailed information.\n\
+ Run `<cyan,bold>cargo test -- --help</>` for test binary options.\n",
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let ws = args.workspace(config)?;
- if args.keep_going() {
- return Err(anyhow::format_err!(
- "\
-unexpected argument `--keep-going` found
-
- tip: to run as many tests as possible without failing fast, use `--no-fail-fast`"
- )
- .into());
- }
-
let mut compile_opts = args.compile_options(
config,
CompileMode::Test,
diff --git a/src/tools/cargo/src/bin/cargo/commands/tree.rs b/src/tools/cargo/src/bin/cargo/commands/tree.rs
index 4472765a9..1fe6a3a14 100644
--- a/src/tools/cargo/src/bin/cargo/commands/tree.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/tree.rs
@@ -96,7 +96,9 @@ pub fn cli() -> Command {
Pass `all` to include all targets.",
)
.arg_manifest_path()
- .after_help("Run `cargo help tree` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help tree</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
@@ -136,7 +138,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
.warn("the --all-targets flag has been changed to --target=all")?;
vec!["all".to_string()]
} else {
- args._values_of("target")
+ args.targets()?
};
let target = tree::Target::from_cli(targets);
diff --git a/src/tools/cargo/src/bin/cargo/commands/uninstall.rs b/src/tools/cargo/src/bin/cargo/commands/uninstall.rs
index 398979bf4..9585d290b 100644
--- a/src/tools/cargo/src/bin/cargo/commands/uninstall.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/uninstall.rs
@@ -13,7 +13,9 @@ pub fn cli() -> Command {
multi_opt("bin", "NAME", "Only uninstall the binary NAME")
.help_heading(heading::TARGET_SELECTION),
)
- .after_help("Run `cargo help uninstall` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help uninstall</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/update.rs b/src/tools/cargo/src/bin/cargo/commands/update.rs
index 31175ef16..e06e8e51e 100644
--- a/src/tools/cargo/src/bin/cargo/commands/update.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/update.rs
@@ -1,26 +1,39 @@
use crate::command_prelude::*;
+use anyhow::anyhow;
use cargo::ops::{self, UpdateOptions};
use cargo::util::print_available_packages;
pub fn cli() -> Command {
subcommand("update")
.about("Update dependencies as recorded in the local lock file")
+ .args([clap::Arg::new("package2")
+ .action(clap::ArgAction::Append)
+ .num_args(1..)
+ .value_name("SPEC")
+ .help_heading(heading::PACKAGE_SELECTION)
+ .group("package-group")
+ .help("Package to update")])
+ .arg(
+ optional_multi_opt("package", "SPEC", "Package to update")
+ .short('p')
+ .hide(true)
+ .help_heading(heading::PACKAGE_SELECTION)
+ .group("package-group"),
+ )
.arg_dry_run("Don't actually write the lockfile")
.arg(
flag(
- "aggressive",
- "Force updating all dependencies of SPEC as well when used with -p",
+ "recursive",
+ "Force updating all dependencies of [SPEC]... as well",
)
+ .alias("aggressive")
.conflicts_with("precise"),
)
.arg(
- opt(
- "precise",
- "Update a single dependency to exactly PRECISE when used with -p",
- )
- .value_name("PRECISE")
- .requires("package"),
+ opt("precise", "Update [SPEC] to exactly PRECISE")
+ .value_name("PRECISE")
+ .requires("package-group"),
)
.arg_quiet()
.arg(
@@ -28,9 +41,10 @@ pub fn cli() -> Command {
.short('w')
.help_heading(heading::PACKAGE_SELECTION),
)
- .arg_package_spec_simple("Package to update")
.arg_manifest_path()
- .after_help("Run `cargo help update` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help update</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
@@ -40,10 +54,26 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
print_available_packages(&ws)?;
}
+ let to_update = if args.contains_id("package") {
+ "package"
+ } else {
+ "package2"
+ };
+ let to_update = values(args, to_update);
+ for crate_name in to_update.iter() {
+ if let Some(toolchain) = crate_name.strip_prefix("+") {
+ return Err(anyhow!(
+ "invalid character `+` in package name: `+{toolchain}`
+ Use `cargo +{toolchain} update` if you meant to use the `{toolchain}` toolchain."
+ )
+ .into());
+ }
+ }
+
let update_opts = UpdateOptions {
- aggressive: args.flag("aggressive"),
+ recursive: args.flag("recursive"),
precise: args.get_one::<String>("precise").map(String::as_str),
- to_update: values(args, "package"),
+ to_update,
dry_run: args.dry_run(),
workspace: args.flag("workspace"),
config,
diff --git a/src/tools/cargo/src/bin/cargo/commands/vendor.rs b/src/tools/cargo/src/bin/cargo/commands/vendor.rs
index 69b4ee380..3f9c2dcaf 100644
--- a/src/tools/cargo/src/bin/cargo/commands/vendor.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/vendor.rs
@@ -32,13 +32,27 @@ pub fn cli() -> Command {
"versioned-dirs",
"Always include version in subdir name",
))
- .arg(flag("no-merge-sources", "Not supported").hide(true))
- .arg(flag("relative-path", "Not supported").hide(true))
- .arg(flag("only-git-deps", "Not supported").hide(true))
- .arg(flag("disallow-duplicates", "Not supported").hide(true))
- .arg_quiet()
+ .arg(unsupported("no-merge-sources"))
+ .arg(unsupported("relative-path"))
+ .arg(unsupported("only-git-deps"))
+ .arg(unsupported("disallow-duplicates"))
+ .arg_quiet_without_unknown_silent_arg_tip()
.arg_manifest_path()
- .after_help("Run `cargo help vendor` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help vendor</>` for more detailed information.\n"
+ ))
+}
+
+fn unsupported(name: &'static str) -> Arg {
+ // When we moved `cargo vendor` into Cargo itself we didn't stabilize a few
+ // flags, so try to provide a helpful error message in that case to ensure
+ // that users currently using the flag aren't tripped up.
+ let value_parser = clap::builder::UnknownArgumentValueParser::suggest("the crates.io `cargo vendor` command has been merged into Cargo")
+ .and_suggest(format!("and the flag `--{name}` isn't supported currently"))
+ .and_suggest("to continue using the flag, execute `cargo-vendor vendor ...`")
+ .and_suggest("to suggest this flag supported in Cargo, file an issue at <https://github.com/rust-lang/cargo/issues/new>");
+
+ flag(name, "").value_parser(value_parser).hide(true)
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
@@ -50,34 +64,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
config.values_mut()?.remove("source");
}
- // When we moved `cargo vendor` into Cargo itself we didn't stabilize a few
- // flags, so try to provide a helpful error message in that case to ensure
- // that users currently using the flag aren't tripped up.
- let crates_io_cargo_vendor_flag = if args.flag("no-merge-sources") {
- Some("--no-merge-sources")
- } else if args.flag("relative-path") {
- Some("--relative-path")
- } else if args.flag("only-git-deps") {
- Some("--only-git-deps")
- } else if args.flag("disallow-duplicates") {
- Some("--disallow-duplicates")
- } else {
- None
- };
- if let Some(flag) = crates_io_cargo_vendor_flag {
- return Err(anyhow::format_err!(
- "\
-the crates.io `cargo vendor` command has now been merged into Cargo itself
-and does not support the flag `{}` currently; to continue using the flag you
-can execute `cargo-vendor vendor ...`, and if you would like to see this flag
-supported in Cargo itself please feel free to file an issue at
-https://github.com/rust-lang/cargo/issues/new
-",
- flag
- )
- .into());
- }
-
let ws = args.workspace(config)?;
let path = args
.get_one::<PathBuf>("path")
diff --git a/src/tools/cargo/src/bin/cargo/commands/verify_project.rs b/src/tools/cargo/src/bin/cargo/commands/verify_project.rs
index 4d5492606..35bb747a4 100644
--- a/src/tools/cargo/src/bin/cargo/commands/verify_project.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/verify_project.rs
@@ -8,7 +8,9 @@ pub fn cli() -> Command {
.about("Check correctness of crate manifest")
.arg_quiet()
.arg_manifest_path()
- .after_help("Run `cargo help verify-project` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help verify-project</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/version.rs b/src/tools/cargo/src/bin/cargo/commands/version.rs
index ac1681f5b..65e1c6c47 100644
--- a/src/tools/cargo/src/bin/cargo/commands/version.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/version.rs
@@ -5,7 +5,9 @@ pub fn cli() -> Command {
subcommand("version")
.about("Show version information")
.arg_quiet()
- .after_help("Run `cargo help version` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help version</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
diff --git a/src/tools/cargo/src/bin/cargo/commands/yank.rs b/src/tools/cargo/src/bin/cargo/commands/yank.rs
index e6700bd2f..62d1821c3 100644
--- a/src/tools/cargo/src/bin/cargo/commands/yank.rs
+++ b/src/tools/cargo/src/bin/cargo/commands/yank.rs
@@ -16,16 +16,16 @@ pub fn cli() -> Command {
"undo",
"Undo a yank, putting a version back into the index",
))
- .arg(opt("index", "Registry index to yank from").value_name("INDEX"))
- .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
+ .arg_index("Registry index URL to yank from")
+ .arg_registry("Registry to yank from")
.arg(opt("token", "API token to use when authenticating").value_name("TOKEN"))
.arg_quiet()
- .after_help("Run `cargo help yank` for more detailed information.\n")
+ .after_help(color_print::cstr!(
+ "Run `<cyan,bold>cargo help yank</>` for more detailed information.\n"
+ ))
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
- let registry = args.registry(config)?;
-
let (krate, version) = resolve_crate(
args.get_one::<String>("crate").map(String::as_str),
args.get_one::<String>("version").map(String::as_str),
@@ -39,9 +39,8 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
krate.map(|s| s.to_string()),
version.map(|s| s.to_string()),
args.get_one::<String>("token").cloned().map(Secret::from),
- args.get_one::<String>("index").cloned(),
+ args.registry_or_index(config)?,
args.flag("undo"),
- registry,
)?;
Ok(())
}
diff --git a/src/tools/cargo/src/bin/cargo/main.rs b/src/tools/cargo/src/bin/cargo/main.rs
index d96c1423d..16e4f24f3 100644
--- a/src/tools/cargo/src/bin/cargo/main.rs
+++ b/src/tools/cargo/src/bin/cargo/main.rs
@@ -41,10 +41,12 @@ fn setup_logger() {
let env = tracing_subscriber::EnvFilter::from_env("CARGO_LOG");
tracing_subscriber::fmt()
+ .with_timer(tracing_subscriber::fmt::time::Uptime::default())
.with_ansi(std::io::IsTerminal::is_terminal(&std::io::stderr()))
.with_writer(std::io::stderr)
.with_env_filter(env)
.init();
+ tracing::trace!(start = humantime::format_rfc3339(std::time::SystemTime::now()).to_string());
}
/// Table for defining the aliases which come builtin in `Cargo`.
@@ -104,17 +106,18 @@ fn list_commands(config: &Config) -> BTreeMap<String, CommandInfo> {
};
for entry in entries.filter_map(|e| e.ok()) {
let path = entry.path();
- let filename = match path.file_name().and_then(|s| s.to_str()) {
- Some(filename) => filename,
- _ => continue,
+ let Some(filename) = path.file_name().and_then(|s| s.to_str()) else {
+ continue;
};
- if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
+ let Some(name) = filename
+ .strip_prefix(prefix)
+ .and_then(|s| s.strip_suffix(suffix))
+ else {
continue;
- }
+ };
if is_executable(entry.path()) {
- let end = filename.len() - suffix.len();
commands.insert(
- filename[prefix.len()..end].to_string(),
+ name.to_string(),
CommandInfo::External { path: path.clone() },
);
}
diff --git a/src/tools/cargo/src/cargo/core/compiler/build_config.rs b/src/tools/cargo/src/cargo/core/compiler/build_config.rs
index 5d4d754bf..f091df2ad 100644
--- a/src/tools/cargo/src/cargo/core/compiler/build_config.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/build_config.rs
@@ -7,7 +7,7 @@ use cargo_util::ProcessBuilder;
use serde::ser;
use std::cell::RefCell;
use std::path::PathBuf;
-use std::sync::Arc;
+use std::rc::Rc;
use std::thread::available_parallelism;
/// Configuration information for a rustc build.
@@ -35,7 +35,7 @@ pub struct BuildConfig {
pub primary_unit_rustc: Option<ProcessBuilder>,
/// A thread used by `cargo fix` to receive messages on a socket regarding
/// the success/failure of applying fixes.
- pub rustfix_diagnostic_server: Arc<RefCell<Option<RustfixDiagnosticServer>>>,
+ pub rustfix_diagnostic_server: Rc<RefCell<Option<RustfixDiagnosticServer>>>,
/// The directory to copy final artifacts to. Note that even if `out_dir` is
/// set, a copy of artifacts still could be found a `target/(debug\release)`
/// as usual.
@@ -113,7 +113,7 @@ impl BuildConfig {
build_plan: false,
unit_graph: false,
primary_unit_rustc: None,
- rustfix_diagnostic_server: Arc::new(RefCell::new(None)),
+ rustfix_diagnostic_server: Rc::new(RefCell::new(None)),
export_dir: None,
future_incompat_report: false,
timing_outputs: Vec::new(),
diff --git a/src/tools/cargo/src/cargo/core/compiler/build_context/mod.rs b/src/tools/cargo/src/cargo/core/compiler/build_context/mod.rs
index f35084e2b..19dee718b 100644
--- a/src/tools/cargo/src/cargo/core/compiler/build_context/mod.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/build_context/mod.rs
@@ -10,7 +10,6 @@ use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
use crate::util::Rustc;
use std::collections::{HashMap, HashSet};
-use std::path::PathBuf;
mod target_info;
pub use self::target_info::{
@@ -120,15 +119,6 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
&self.target_data.rustc
}
- /// Gets the user-specified linker for a particular host or target.
- pub fn linker(&self, kind: CompileKind) -> Option<PathBuf> {
- self.target_data
- .target_config(kind)
- .linker
- .as_ref()
- .map(|l| l.val.clone().resolve_program(self.config))
- }
-
/// Gets the host architecture triple.
///
/// For example, x86_64-unknown-linux-gnu, would be
diff --git a/src/tools/cargo/src/cargo/core/compiler/build_context/target_info.rs b/src/tools/cargo/src/cargo/core/compiler/build_context/target_info.rs
index 754adcf3c..c3b3dd48a 100644
--- a/src/tools/cargo/src/cargo/core/compiler/build_context/target_info.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/build_context/target_info.rs
@@ -367,9 +367,8 @@ impl TargetInfo {
&*v.insert(value)
}
};
- let (prefix, suffix) = match *crate_type_info {
- Some((ref prefix, ref suffix)) => (prefix, suffix),
- None => return Ok(None),
+ let Some((prefix, suffix)) = crate_type_info else {
+ return Ok(None);
};
let mut ret = vec![FileType {
suffix: suffix.clone(),
@@ -466,7 +465,7 @@ impl TargetInfo {
// the names to match.
should_replace_hyphens: false,
})
- } else if target_triple.ends_with("-msvc") {
+ } else if target_triple.ends_with("-msvc") || target_triple.ends_with("-uefi") {
ret.push(FileType {
suffix: ".pdb".to_string(),
prefix: prefix.clone(),
@@ -612,13 +611,12 @@ fn parse_crate_type(
if not_supported {
return Ok(None);
}
- let line = match lines.next() {
- Some(line) => line,
- None => anyhow::bail!(
+ let Some(line) = lines.next() else {
+ anyhow::bail!(
"malformed output when learning about crate-type {} information\n{}",
crate_type,
output_err_info(cmd, output, error)
- ),
+ )
};
let mut parts = line.trim().split("___");
let prefix = parts.next().unwrap();
@@ -948,7 +946,7 @@ impl<'cfg> RustcTargetData<'cfg> {
}
/// Insert `kind` into our `target_info` and `target_config` members if it isn't present yet.
- fn merge_compile_kind(&mut self, kind: CompileKind) -> CargoResult<()> {
+ pub fn merge_compile_kind(&mut self, kind: CompileKind) -> CargoResult<()> {
if let CompileKind::Target(target) = kind {
if !self.target_config.contains_key(&target) {
self.target_config
@@ -978,9 +976,8 @@ impl<'cfg> RustcTargetData<'cfg> {
pub fn dep_platform_activated(&self, dep: &Dependency, kind: CompileKind) -> bool {
// If this dependency is only available for certain platforms,
// make sure we're only enabling it for that platform.
- let platform = match dep.platform() {
- Some(p) => p,
- None => return true,
+ let Some(platform) = dep.platform() else {
+ return true;
};
let name = self.short_name(&kind);
platform.matches(name, self.cfg(kind))
@@ -1058,13 +1055,12 @@ impl RustDocFingerprint {
serde_json::to_string(&actual_rustdoc_target_data)?,
)
};
- let rustdoc_data = match paths::read(&fingerprint_path) {
- Ok(rustdoc_data) => rustdoc_data,
+ let Ok(rustdoc_data) = paths::read(&fingerprint_path) else {
// If the fingerprint does not exist, do not clear out the doc
// directories. Otherwise this ran into problems where projects
// like rustbuild were creating the doc directory before running
// `cargo doc` in a way that deleting it would break it.
- Err(_) => return write_fingerprint(),
+ return write_fingerprint();
};
match serde_json::from_str::<RustDocFingerprint>(&rustdoc_data) {
Ok(fingerprint) => {
diff --git a/src/tools/cargo/src/cargo/core/compiler/build_plan.rs b/src/tools/cargo/src/cargo/core/compiler/build_plan.rs
index a823aa952..a024d4990 100644
--- a/src/tools/cargo/src/cargo/core/compiler/build_plan.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/build_plan.rs
@@ -86,10 +86,7 @@ impl Invocation {
);
}
for (var, value) in cmd.get_envs() {
- let value = match value {
- Some(s) => s,
- None => continue,
- };
+ let Some(value) = value else { continue };
self.env.insert(
var.clone(),
value
diff --git a/src/tools/cargo/src/cargo/core/compiler/compilation.rs b/src/tools/cargo/src/cargo/core/compiler/compilation.rs
index b263119b0..e03a08d39 100644
--- a/src/tools/cargo/src/cargo/core/compiler/compilation.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/compilation.rs
@@ -104,6 +104,8 @@ pub struct Compilation<'cfg> {
primary_rustc_process: Option<ProcessBuilder>,
target_runners: HashMap<CompileKind, Option<(PathBuf, Vec<String>)>>,
+ /// The linker to use for each host or target.
+ target_linkers: HashMap<CompileKind, Option<PathBuf>>,
}
impl<'cfg> Compilation<'cfg> {
@@ -150,6 +152,13 @@ impl<'cfg> Compilation<'cfg> {
.chain(Some(&CompileKind::Host))
.map(|kind| Ok((*kind, target_runner(bcx, *kind)?)))
.collect::<CargoResult<HashMap<_, _>>>()?,
+ target_linkers: bcx
+ .build_config
+ .requested_kinds
+ .iter()
+ .chain(Some(&CompileKind::Host))
+ .map(|kind| Ok((*kind, target_linker(bcx, *kind)?)))
+ .collect::<CargoResult<HashMap<_, _>>>()?,
})
}
@@ -221,6 +230,11 @@ impl<'cfg> Compilation<'cfg> {
self.target_runners.get(&kind).and_then(|x| x.as_ref())
}
+ /// Gets the user-specified linker for a particular host or target.
+ pub fn target_linker(&self, kind: CompileKind) -> Option<PathBuf> {
+ self.target_linkers.get(&kind).and_then(|x| x.clone())
+ }
+
/// Returns a [`ProcessBuilder`] appropriate for running a process for the
/// target platform. This is typically used for `cargo run` and `cargo
/// test`.
@@ -312,6 +326,7 @@ impl<'cfg> Compilation<'cfg> {
// crate properties which might require rebuild upon change
// consider adding the corresponding properties to the hash
// in BuildContext::target_metadata()
+ let rust_version = pkg.rust_version().as_ref().map(ToString::to_string);
cmd.env("CARGO_MANIFEST_DIR", pkg.root())
.env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string())
.env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string())
@@ -342,7 +357,7 @@ impl<'cfg> Compilation<'cfg> {
.env("CARGO_PKG_AUTHORS", &pkg.authors().join(":"))
.env(
"CARGO_PKG_RUST_VERSION",
- &pkg.rust_version().unwrap_or(&String::new()),
+ &rust_version.as_deref().unwrap_or_default(),
)
.env(
"CARGO_PKG_README",
@@ -441,3 +456,39 @@ fn target_runner(
)
}))
}
+
+/// Gets the user-specified linker for a particular host or target from the configuration.
+fn target_linker(bcx: &BuildContext<'_, '_>, kind: CompileKind) -> CargoResult<Option<PathBuf>> {
+ // Try host.linker and target.{}.linker.
+ if let Some(path) = bcx
+ .target_data
+ .target_config(kind)
+ .linker
+ .as_ref()
+ .map(|l| l.val.clone().resolve_program(bcx.config))
+ {
+ return Ok(Some(path));
+ }
+
+ // Try target.'cfg(...)'.linker.
+ let target_cfg = bcx.target_data.info(kind).cfg();
+ let mut cfgs = bcx
+ .config
+ .target_cfgs()?
+ .iter()
+ .filter_map(|(key, cfg)| cfg.linker.as_ref().map(|linker| (key, linker)))
+ .filter(|(key, _linker)| CfgExpr::matches_key(key, target_cfg));
+ let matching_linker = cfgs.next();
+ if let Some((key, linker)) = cfgs.next() {
+ anyhow::bail!(
+ "several matching instances of `target.'cfg(..)'.linker` in configurations\n\
+ first match `{}` located in {}\n\
+ second match `{}` located in {}",
+ matching_linker.unwrap().0,
+ matching_linker.unwrap().1.definition,
+ key,
+ linker.definition
+ );
+ }
+ Ok(matching_linker.map(|(_k, linker)| linker.val.clone().resolve_program(bcx.config)))
+}
diff --git a/src/tools/cargo/src/cargo/core/compiler/context/compilation_files.rs b/src/tools/cargo/src/cargo/core/compiler/context/compilation_files.rs
index 126e17112..d83dbf10c 100644
--- a/src/tools/cargo/src/cargo/core/compiler/context/compilation_files.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/context/compilation_files.rs
@@ -547,7 +547,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
/// Gets the metadata hash for the given [`Unit`].
///
-/// Whne a metadata hash doesn't exist for the given unit,
+/// When a metadata hash doesn't exist for the given unit,
/// this calls itself recursively to compute metadata hashes of all its dependencies.
/// See [`compute_metadata`] for how a single metadata hash is computed.
fn metadata_of<'a>(
diff --git a/src/tools/cargo/src/cargo/core/compiler/context/mod.rs b/src/tools/cargo/src/cargo/core/compiler/context/mod.rs
index 3f13f086c..010fe2793 100644
--- a/src/tools/cargo/src/cargo/core/compiler/context/mod.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/context/mod.rs
@@ -272,7 +272,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
unit: unit.clone(),
args,
unstable_opts,
- linker: self.bcx.linker(unit.kind),
+ linker: self.compilation.target_linker(unit.kind).clone(),
script_meta,
env: artifact::get_env(&self, self.unit_deps(unit))?,
});
diff --git a/src/tools/cargo/src/cargo/core/compiler/custom_build.rs b/src/tools/cargo/src/cargo/core/compiler/custom_build.rs
index 85306aaac..3eeeaa0ee 100644
--- a/src/tools/cargo/src/cargo/core/compiler/custom_build.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/custom_build.rs
@@ -240,7 +240,7 @@ fn emit_build_output(
///
/// The construction includes:
///
-/// * Set environment varibles for the build script run.
+/// * Set environment variables for the build script run.
/// * Create the output dir (`OUT_DIR`) for the build script output.
/// * Determine if the build script needs a re-run.
/// * Run the build script and store its output.
@@ -281,7 +281,7 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
.env("NUM_JOBS", &bcx.jobs().to_string())
.env("TARGET", bcx.target_data.short_name(&unit.kind))
.env("DEBUG", debug.to_string())
- .env("OPT_LEVEL", &unit.profile.opt_level.to_string())
+ .env("OPT_LEVEL", &unit.profile.opt_level)
.env(
"PROFILE",
match unit.profile.root {
@@ -299,11 +299,8 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
cmd.env(&var, value);
}
- if let Some(linker) = &bcx.target_data.target_config(unit.kind).linker {
- cmd.env(
- "RUSTC_LINKER",
- linker.val.clone().resolve_program(bcx.config),
- );
+ if let Some(linker) = &cx.compilation.target_linker(unit.kind) {
+ cmd.env("RUSTC_LINKER", linker);
}
if let Some(links) = unit.pkg.manifest().links() {
@@ -446,7 +443,7 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
))
})?;
let data = &script_output.metadata;
- for &(ref key, ref value) in data.iter() {
+ for (key, value) in data.iter() {
cmd.env(
&format!("DEP_{}_{}", super::envify(&name), super::envify(key)),
value,
@@ -684,32 +681,24 @@ impl BuildOutput {
Ok(line) => line.trim(),
Err(..) => continue,
};
- let mut iter = line.splitn(2, ':');
- if iter.next() != Some("cargo") {
- // skip this line since it doesn't start with "cargo:"
- continue;
- }
- let data = match iter.next() {
- Some(val) => {
+ let data = match line.split_once(':') {
+ Some(("cargo", val)) => {
if val.starts_with(":") {
// Line started with `cargo::`.
- bail!("unsupported output in {}: `{}`\n\
+ bail!("unsupported output in {whence}: `{line}`\n\
Found a `cargo::key=value` build directive which is reserved for future use.\n\
Either change the directive to `cargo:key=value` syntax (note the single `:`) or upgrade your version of Rust.\n\
See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script \
- for more information about build script outputs.", whence, line);
+ for more information about build script outputs.");
}
val
}
- None => continue,
+ _ => continue,
};
// getting the `key=value` part of the line
- let mut iter = data.splitn(2, '=');
- let key = iter.next();
- let value = iter.next();
- let (key, value) = match (key, value) {
- (Some(a), Some(b)) => (a, b.trim_end()),
+ let (key, value) = match data.split_once('=') {
+ Some((a,b)) => (a, b.trim_end()),
// Line started with `cargo:` but didn't match `key=value`.
_ => bail!("invalid output in {}: `{}`\n\
Expected a line with `cargo:key=value` with an `=` character, \
@@ -768,9 +757,7 @@ impl BuildOutput {
check_and_add_target!("bin", Target::is_bin, LinkArgTarget::Bin);
}
"rustc-link-arg-bin" => {
- let mut parts = value.splitn(2, '=');
- let bin_name = parts.next().unwrap().to_string();
- let arg = parts.next().ok_or_else(|| {
+ let (bin_name, arg) = value.split_once('=').ok_or_else(|| {
anyhow::format_err!(
"invalid instruction `cargo:{}={}` from {}\n\
The instruction should have the form cargo:{}=BIN=ARG",
@@ -793,7 +780,10 @@ impl BuildOutput {
bin_name
);
}
- linker_args.push((LinkArgTarget::SingleBin(bin_name), arg.to_string()));
+ linker_args.push((
+ LinkArgTarget::SingleBin(bin_name.to_owned()),
+ arg.to_string(),
+ ));
}
"rustc-link-arg-tests" => {
check_and_add_target!("test", Target::is_test, LinkArgTarget::Test);
@@ -837,7 +827,7 @@ impl BuildOutput {
None => return false,
Some(n) => n,
};
- // ALLOWED: the process of rustc boostrapping reads this through
+ // ALLOWED: the process of rustc bootstrapping reads this through
// `std::env`. We should make the behavior consistent. Also, we
// don't advertise this for bypassing nightly.
#[allow(clippy::disallowed_methods)]
@@ -939,12 +929,9 @@ impl BuildOutput {
///
/// [`cargo:rustc-env`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-env
pub fn parse_rustc_env(value: &str, whence: &str) -> CargoResult<(String, String)> {
- let mut iter = value.splitn(2, '=');
- let name = iter.next();
- let val = iter.next();
- match (name, val) {
- (Some(n), Some(v)) => Ok((n.to_owned(), v.to_owned())),
- _ => bail!("Variable rustc-env has no value in {}: {}", whence, value),
+ match value.split_once('=') {
+ Some((n, v)) => Ok((n.to_owned(), v.to_owned())),
+ _ => bail!("Variable rustc-env has no value in {whence}: {value}"),
}
}
}
diff --git a/src/tools/cargo/src/cargo/core/compiler/fingerprint/mod.rs b/src/tools/cargo/src/cargo/core/compiler/fingerprint/mod.rs
index 2e6fb7eed..b1040be41 100644
--- a/src/tools/cargo/src/cargo/core/compiler/fingerprint/mod.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/fingerprint/mod.rs
@@ -811,9 +811,8 @@ impl LocalFingerprint {
// rustc.
LocalFingerprint::CheckDepInfo { dep_info } => {
let dep_info = target_root.join(dep_info);
- let info = match parse_dep_info(pkg_root, target_root, &dep_info)? {
- Some(info) => info,
- None => return Ok(Some(StaleItem::MissingFile(dep_info))),
+ let Some(info) = parse_dep_info(pkg_root, target_root, &dep_info)? else {
+ return Ok(Some(StaleItem::MissingFile(dep_info)));
};
for (key, previous) in info.env.iter() {
let current = if key == CARGO_ENV {
@@ -1038,16 +1037,16 @@ impl Fingerprint {
for (a, b) in self.deps.iter().zip(old.deps.iter()) {
if a.name != b.name {
return DirtyReason::UnitDependencyNameChanged {
- old: b.name.clone(),
- new: a.name.clone(),
+ old: b.name,
+ new: a.name,
};
}
if a.fingerprint.hash_u64() != b.fingerprint.hash_u64() {
return DirtyReason::UnitDependencyInfoChanged {
- new_name: a.name.clone(),
+ new_name: a.name,
new_fingerprint: a.fingerprint.hash_u64(),
- old_name: b.name.clone(),
+ old_name: b.name,
old_fingerprint: b.fingerprint.hash_u64(),
};
}
@@ -1103,16 +1102,12 @@ impl Fingerprint {
}
let opt_max = mtimes.iter().max_by_key(|kv| kv.1);
- let (max_path, max_mtime) = match opt_max {
- Some(mtime) => mtime,
-
+ let Some((max_path, max_mtime)) = opt_max else {
// We had no output files. This means we're an overridden build
// script and we're just always up to date because we aren't
// watching the filesystem.
- None => {
- self.fs_status = FsStatus::UpToDate { mtimes };
- return Ok(());
- }
+ self.fs_status = FsStatus::UpToDate { mtimes };
+ return Ok(());
};
debug!(
"max output mtime for {:?} is {:?} {}",
@@ -1127,9 +1122,7 @@ impl Fingerprint {
| FsStatus::StaleItem(_)
| FsStatus::StaleDependency { .. }
| FsStatus::StaleDepFingerprint { .. } => {
- self.fs_status = FsStatus::StaleDepFingerprint {
- name: dep.name.clone(),
- };
+ self.fs_status = FsStatus::StaleDepFingerprint { name: dep.name };
return Ok(());
}
};
@@ -1171,7 +1164,7 @@ impl Fingerprint {
);
self.fs_status = FsStatus::StaleDependency {
- name: dep.name.clone(),
+ name: dep.name,
dep_mtime: *dep_mtime,
max_mtime: *max_mtime,
};
@@ -1426,7 +1419,7 @@ fn calculate_normal(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Finger
let m = unit.pkg.manifest().metadata();
let metadata = util::hash_u64((&m.authors, &m.description, &m.homepage, &m.repository));
let mut config = StableHasher::new();
- if let Some(linker) = cx.bcx.linker(unit.kind) {
+ if let Some(linker) = cx.compilation.target_linker(unit.kind) {
linker.hash(&mut config);
}
if unit.mode.is_doc() && cx.bcx.config.cli_unstable().rustdoc_map {
@@ -1771,7 +1764,7 @@ fn compare_old_fingerprint(
/// Logs the result of fingerprint comparison.
///
-/// TODO: Obsolete and mostly superceded by [`DirtyReason`]. Could be removed.
+/// TODO: Obsolete and mostly superseded by [`DirtyReason`]. Could be removed.
fn log_compare(unit: &Unit, compare: &CargoResult<Option<DirtyReason>>) {
match compare {
Ok(None) => {}
@@ -1808,16 +1801,12 @@ pub fn parse_dep_info(
target_root: &Path,
dep_info: &Path,
) -> CargoResult<Option<RustcDepInfo>> {
- let data = match paths::read_bytes(dep_info) {
- Ok(data) => data,
- Err(_) => return Ok(None),
+ let Ok(data) = paths::read_bytes(dep_info) else {
+ return Ok(None);
};
- let info = match EncodedDepInfo::parse(&data) {
- Some(info) => info,
- None => {
- tracing::warn!("failed to parse cargo's dep-info at {:?}", dep_info);
- return Ok(None);
- }
+ let Some(info) = EncodedDepInfo::parse(&data) else {
+ tracing::warn!("failed to parse cargo's dep-info at {:?}", dep_info);
+ return Ok(None);
};
let mut ret = RustcDepInfo::default();
ret.env = info.env;
@@ -1831,7 +1820,7 @@ pub fn parse_dep_info(
Ok(Some(ret))
}
-/// Calcuates the fingerprint of a unit thats contains no dep-info files.
+/// Calculates the fingerprint of a unit thats contains no dep-info files.
fn pkg_fingerprint(bcx: &BuildContext<'_, '_>, pkg: &Package) -> CargoResult<String> {
let source_id = pkg.package_id().source_id();
let sources = bcx.packages.sources();
@@ -1852,9 +1841,8 @@ where
I: IntoIterator,
I::Item: AsRef<Path>,
{
- let reference_mtime = match paths::mtime(reference) {
- Ok(mtime) => mtime,
- Err(..) => return Some(StaleItem::MissingFile(reference.to_path_buf())),
+ let Ok(reference_mtime) = paths::mtime(reference) else {
+ return Some(StaleItem::MissingFile(reference.to_path_buf()));
};
let skipable_dirs = if let Ok(cargo_home) = home::cargo_home() {
@@ -1882,9 +1870,8 @@ where
let path_mtime = match mtime_cache.entry(path.to_path_buf()) {
Entry::Occupied(o) => *o.get(),
Entry::Vacant(v) => {
- let mtime = match paths::mtime_recursive(path) {
- Ok(mtime) => mtime,
- Err(..) => return Some(StaleItem::MissingFile(path.to_path_buf())),
+ let Ok(mtime) = paths::mtime_recursive(path) else {
+ return Some(StaleItem::MissingFile(path.to_path_buf()));
};
*v.insert(mtime)
}
@@ -2156,9 +2143,8 @@ pub fn parse_rustc_dep_info(rustc_dep_info: &Path) -> CargoResult<RustcDepInfo>
for line in contents.lines() {
if let Some(rest) = line.strip_prefix("# env-dep:") {
let mut parts = rest.splitn(2, '=');
- let env_var = match parts.next() {
- Some(s) => s,
- None => continue,
+ let Some(env_var) = parts.next() else {
+ continue;
};
let env_val = match parts.next() {
Some(s) => Some(unescape_env(s)?),
diff --git a/src/tools/cargo/src/cargo/core/compiler/future_incompat.rs b/src/tools/cargo/src/cargo/core/compiler/future_incompat.rs
index ccea28b94..907a0f97d 100644
--- a/src/tools/cargo/src/cargo/core/compiler/future_incompat.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/future_incompat.rs
@@ -34,9 +34,10 @@
//! [2]: https://github.com/rust-lang/rust/blob/9bb6e60d1f1360234aae90c97964c0fa5524f141/compiler/rustc_errors/src/json.rs#L312-L315
use crate::core::compiler::BuildContext;
-use crate::core::{Dependency, PackageId, QueryKind, Workspace};
+use crate::core::{Dependency, PackageId, Workspace};
+use crate::sources::source::QueryKind;
use crate::sources::SourceConfigMap;
-use crate::util::{iter_join, CargoResult, Config};
+use crate::util::{iter_join, CargoResult};
use anyhow::{bail, format_err, Context};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
@@ -223,12 +224,8 @@ impl OnDiskReports {
self.reports.last().map(|r| r.id).unwrap()
}
- pub fn get_report(
- &self,
- id: u32,
- config: &Config,
- package: Option<&str>,
- ) -> CargoResult<String> {
+ /// Returns an ANSI-styled report
+ pub fn get_report(&self, id: u32, package: Option<&str>) -> CargoResult<String> {
let report = self.reports.iter().find(|r| r.id == id).ok_or_else(|| {
let available = iter_join(self.reports.iter().map(|r| r.id.to_string()), ", ");
format_err!(
@@ -266,15 +263,6 @@ impl OnDiskReports {
};
to_display += &package_report;
- let shell = config.shell();
-
- let to_display = if shell.err_supports_color() && shell.out_supports_color() {
- to_display
- } else {
- strip_ansi_escapes::strip(&to_display)
- .map(|v| String::from_utf8(v).expect("utf8"))
- .expect("strip should never fail")
- };
Ok(to_display)
}
}
@@ -332,13 +320,11 @@ fn get_updates(ws: &Workspace<'_>, package_ids: &BTreeSet<PackageId>) -> Option<
let mut summaries = Vec::new();
while !package_ids.is_empty() {
package_ids.retain(|&pkg_id| {
- let source = match sources.get_mut(&pkg_id.source_id()) {
- Some(s) => s,
- None => return false,
+ let Some(source) = sources.get_mut(&pkg_id.source_id()) else {
+ return false;
};
- let dep = match Dependency::parse(pkg_id.name(), None, pkg_id.source_id()) {
- Ok(dep) => dep,
- Err(_) => return false,
+ let Ok(dep) = Dependency::parse(pkg_id.name(), None, pkg_id.source_id()) else {
+ return false;
};
match source.query_vec(&dep, QueryKind::Exact) {
Poll::Ready(Ok(sum)) => {
diff --git a/src/tools/cargo/src/cargo/core/compiler/job_queue/mod.rs b/src/tools/cargo/src/cargo/core/compiler/job_queue/mod.rs
index 26fcd4826..738c8c267 100644
--- a/src/tools/cargo/src/cargo/core/compiler/job_queue/mod.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/job_queue/mod.rs
@@ -941,9 +941,8 @@ impl<'cfg> DrainState<'cfg> {
cx: &mut Context<'_, '_>,
) -> CargoResult<()> {
let outputs = cx.build_script_outputs.lock().unwrap();
- let metadata = match cx.find_build_script_metadata(unit) {
- Some(metadata) => metadata,
- None => return Ok(()),
+ let Some(metadata) = cx.find_build_script_metadata(unit) else {
+ return Ok(());
};
let bcx = &mut cx.bcx;
if let Some(output) = outputs.get(metadata) {
diff --git a/src/tools/cargo/src/cargo/core/compiler/links.rs b/src/tools/cargo/src/cargo/core/compiler/links.rs
index 4cef2eb39..cfbf92ef0 100644
--- a/src/tools/cargo/src/cargo/core/compiler/links.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/links.rs
@@ -27,9 +27,8 @@ pub fn validate_links(resolve: &Resolve, unit_graph: &UnitGraph) -> CargoResult<
if !validated.insert(unit.pkg.package_id()) {
continue;
}
- let lib = match unit.pkg.manifest().links() {
- Some(lib) => lib,
- None => continue,
+ let Some(lib) = unit.pkg.manifest().links() else {
+ continue;
};
if let Some(&prev) = links.get(lib) {
let prev_path = resolve
diff --git a/src/tools/cargo/src/cargo/core/compiler/mod.rs b/src/tools/cargo/src/cargo/core/compiler/mod.rs
index 7024a2ac5..b0f15bd61 100644
--- a/src/tools/cargo/src/cargo/core/compiler/mod.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/mod.rs
@@ -11,7 +11,7 @@
//! like what rustc has done[^1]. Also, no one knows if Cargo really needs that.
//! To be pragmatic, here we list a handful of items you may want to learn:
//!
-//! * [`BuildContext`] is a static context containg all information you need
+//! * [`BuildContext`] is a static context containing all information you need
//! before a build gets started.
//! * [`Context`] is the center of the world, coordinating a running build and
//! collecting information from it.
@@ -19,7 +19,7 @@
//! * [`fingerprint`] not only defines but also executes a set of rules to
//! determine if a re-compile is needed.
//! * [`job_queue`] is where the parallelism, job scheduling, and communication
-//! machinary happen between Cargo and the compiler.
+//! machinery happen between Cargo and the compiler.
//! * [`layout`] defines and manages output artifacts of a build in the filesystem.
//! * [`unit_dependencies`] is for building a dependency graph for compilation
//! from a result of dependency resolution.
@@ -202,7 +202,6 @@ fn compile<'cfg>(
&unit.target,
cx.files().message_cache_path(unit),
cx.bcx.build_config.message_format,
- cx.bcx.config.shell().err_supports_color(),
unit.show_warnings(bcx.config),
);
// Need to link targets on both the dirty and fresh.
@@ -252,7 +251,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc<dyn Executor>) -> Car
let mut rustc = prepare_rustc(cx, unit)?;
let build_plan = cx.bcx.build_config.build_plan;
- let name = unit.pkg.name().to_string();
+ let name = unit.pkg.name();
let buildkey = unit.buildkey();
let outputs = cx.outputs(unit)?;
@@ -543,12 +542,9 @@ fn link_targets(cx: &mut Context<'_, '_>, unit: &Unit, fresh: bool) -> CargoResu
if !src.exists() {
continue;
}
- let dst = match output.hardlink.as_ref() {
- Some(dst) => dst,
- None => {
- destinations.push(src.clone());
- continue;
- }
+ let Some(dst) = output.hardlink.as_ref() else {
+ destinations.push(src.clone());
+ continue;
};
destinations.push(dst.clone());
paths::link_or_copy(src, dst)?;
@@ -634,19 +630,9 @@ where
{
let mut search_path = vec![];
for dir in paths {
- let dir = match dir.to_str() {
- Some(s) => {
- let mut parts = s.splitn(2, '=');
- match (parts.next(), parts.next()) {
- (Some("native"), Some(path))
- | (Some("crate"), Some(path))
- | (Some("dependency"), Some(path))
- | (Some("framework"), Some(path))
- | (Some("all"), Some(path)) => path.into(),
- _ => dir.clone(),
- }
- }
- None => dir.clone(),
+ let dir = match dir.to_str().and_then(|s| s.split_once("=")) {
+ Some(("native" | "crate" | "dependency" | "framework" | "all", path)) => path.into(),
+ _ => dir.clone(),
};
if dir.starts_with(&root_output) {
search_path.push(dir);
@@ -785,7 +771,7 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
paths::create_dir_all(&doc_dir)?;
let target_desc = unit.target.description_named();
- let name = unit.pkg.name().to_string();
+ let name = unit.pkg.name();
let build_script_outputs = Arc::clone(&cx.build_script_outputs);
let package_id = unit.pkg.package_id();
let manifest_path = PathBuf::from(unit.pkg.manifest_path());
@@ -1117,7 +1103,10 @@ fn build_base_args(cx: &Context<'_, '_>, cmd: &mut ProcessBuilder, unit: &Unit)
cmd,
"-C",
"linker=",
- bcx.linker(unit.kind).as_ref().map(|s| s.as_ref()),
+ cx.compilation
+ .target_linker(unit.kind)
+ .as_ref()
+ .map(|s| s.as_ref()),
);
if incremental {
let dir = cx.files().layout(unit.kind).incremental().as_os_str();
@@ -1328,7 +1317,7 @@ fn add_custom_flags(
cmd.arg("--check-cfg").arg(check_cfg);
}
}
- for &(ref name, ref value) in output.env.iter() {
+ for (name, value) in output.env.iter() {
cmd.env(name, value);
}
}
@@ -1426,8 +1415,6 @@ fn envify(s: &str) -> String {
struct OutputOptions {
/// What format we're emitting from Cargo itself.
format: MessageFormat,
- /// Whether or not to display messages in color.
- color: bool,
/// Where to write the JSON messages to support playback later if the unit
/// is fresh. The file is created lazily so that in the normal case, lots
/// of empty files are not created. If this is None, the output will not
@@ -1449,14 +1436,12 @@ struct OutputOptions {
impl OutputOptions {
fn new(cx: &Context<'_, '_>, unit: &Unit) -> OutputOptions {
- let color = cx.bcx.config.shell().err_supports_color();
let path = cx.files().message_cache_path(unit);
// Remove old cache, ignore ENOENT, which is the common case.
drop(fs::remove_file(&path));
let cache_cell = Some((path, LazyCell::new()));
OutputOptions {
format: cx.bcx.build_config.message_format,
- color,
cache_cell,
show_diagnostics: true,
warnings_seen: 0,
@@ -1596,15 +1581,7 @@ fn on_stderr_line_inner(
if msg.rendered.ends_with('\n') {
msg.rendered.pop();
}
- let rendered = if options.color {
- msg.rendered
- } else {
- // Strip only fails if the Writer fails, which is Cursor
- // on a Vec, which should never fail.
- strip_ansi_escapes::strip(&msg.rendered)
- .map(|v| String::from_utf8(v).expect("utf8"))
- .expect("strip should never fail")
- };
+ let rendered = msg.rendered;
if options.show_diagnostics {
let machine_applicable: bool = msg
.children
@@ -1635,9 +1612,7 @@ fn on_stderr_line_inner(
other: std::collections::BTreeMap<String, serde_json::Value>,
}
if let Ok(mut error) = serde_json::from_str::<CompilerMessage>(compiler_message.get()) {
- error.rendered = strip_ansi_escapes::strip(&error.rendered)
- .map(|v| String::from_utf8(v).expect("utf8"))
- .unwrap_or(error.rendered);
+ error.rendered = anstream::adapter::strip_str(&error.rendered).to_string();
let new_line = serde_json::to_string(&error)?;
let new_msg: Box<serde_json::value::RawValue> = serde_json::from_str(&new_line)?;
compiler_message = new_msg;
@@ -1709,13 +1684,11 @@ fn replay_output_cache(
target: &Target,
path: PathBuf,
format: MessageFormat,
- color: bool,
show_diagnostics: bool,
) -> Work {
let target = target.clone();
let mut options = OutputOptions {
format,
- color,
cache_cell: None,
show_diagnostics,
warnings_seen: 0,
diff --git a/src/tools/cargo/src/cargo/core/compiler/standard_lib.rs b/src/tools/cargo/src/cargo/core/compiler/standard_lib.rs
index c456c58d5..5272c211b 100644
--- a/src/tools/cargo/src/cargo/core/compiler/standard_lib.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/standard_lib.rs
@@ -62,7 +62,7 @@ pub(crate) fn std_crates(config: &Config, units: Option<&[Unit]>) -> Option<Vec<
/// Resolve the standard library dependencies.
pub fn resolve_std<'cfg>(
ws: &Workspace<'cfg>,
- target_data: &RustcTargetData<'cfg>,
+ target_data: &mut RustcTargetData<'cfg>,
build_config: &BuildConfig,
crates: &[String],
) -> CargoResult<(PackageSet<'cfg>, Resolve, ResolvedFeatures)> {
@@ -145,6 +145,7 @@ pub fn resolve_std<'cfg>(
let cli_features = CliFeatures::from_command_line(
&features, /*all_features*/ false, /*uses_default_features*/ false,
)?;
+ let max_rust_version = ws.rust_version();
let resolve = ops::resolve_ws_with_opts(
&std_ws,
target_data,
@@ -153,6 +154,7 @@ pub fn resolve_std<'cfg>(
&specs,
HasDevUnits::No,
crate::core::resolver::features::ForceAllTargets::No,
+ max_rust_version,
)?;
Ok((
resolve.pkg_set,
diff --git a/src/tools/cargo/src/cargo/core/compiler/timings.rs b/src/tools/cargo/src/cargo/core/compiler/timings.rs
index 57ded9bf8..7c388bd10 100644
--- a/src/tools/cargo/src/cargo/core/compiler/timings.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/timings.rs
@@ -8,6 +8,7 @@ use crate::core::compiler::{BuildContext, Context, TimingOutput};
use crate::core::PackageId;
use crate::util::cpu::State;
use crate::util::machine_message::{self, Message};
+use crate::util::style;
use crate::util::{CargoResult, Config};
use anyhow::Context as _;
use cargo_util::paths;
@@ -193,9 +194,8 @@ impl<'cfg> Timings<'cfg> {
// `id` may not always be active. "fresh" units unconditionally
// generate `Message::Finish`, but this active map only tracks dirty
// units.
- let unit_time = match self.active.get_mut(&id) {
- Some(ut) => ut,
- None => return,
+ let Some(unit_time) = self.active.get_mut(&id) else {
+ return;
};
let t = self.start.elapsed().as_secs_f64();
unit_time.rmeta_time = Some(t - unit_time.start);
@@ -211,9 +211,8 @@ impl<'cfg> Timings<'cfg> {
return;
}
// See note above in `unit_rmeta_finished`, this may not always be active.
- let mut unit_time = match self.active.remove(&id) {
- Some(ut) => ut,
- None => return,
+ let Some(mut unit_time) = self.active.remove(&id) else {
+ return;
};
let t = self.start.elapsed().as_secs_f64();
unit_time.duration = t - unit_time.start;
@@ -264,9 +263,8 @@ impl<'cfg> Timings<'cfg> {
if !self.enabled {
return;
}
- let prev = match &mut self.last_cpu_state {
- Some(state) => state,
- None => return,
+ let Some(prev) = &mut self.last_cpu_state else {
+ return;
};
// Don't take samples too frequently, even if requested.
let now = Instant::now();
@@ -352,7 +350,7 @@ impl<'cfg> Timings<'cfg> {
paths::link_or_copy(&filename, &unstamped_filename)?;
self.config
.shell()
- .status_with_color("Timing", msg, termcolor::Color::Cyan)?;
+ .status_with_color("Timing", msg, &style::NOTE)?;
Ok(())
}
diff --git a/src/tools/cargo/src/cargo/core/compiler/unit_dependencies.rs b/src/tools/cargo/src/cargo/core/compiler/unit_dependencies.rs
index 686822356..7116ba207 100644
--- a/src/tools/cargo/src/cargo/core/compiler/unit_dependencies.rs
+++ b/src/tools/cargo/src/cargo/core/compiler/unit_dependencies.rs
@@ -273,10 +273,9 @@ fn compute_deps(
let mut ret = Vec::new();
let mut dev_deps = Vec::new();
for (dep_pkg_id, deps) in state.deps(unit, unit_for) {
- let dep_lib = match calc_artifact_deps(unit, unit_for, dep_pkg_id, &deps, state, &mut ret)?
- {
- Some(lib) => lib,
- None => continue,
+ let Some(dep_lib) = calc_artifact_deps(unit, unit_for, dep_pkg_id, &deps, state, &mut ret)?
+ else {
+ continue;
};
let dep_pkg = state.get(dep_pkg_id);
let mode = check_or_build_mode(unit.mode, dep_lib);
@@ -412,12 +411,9 @@ fn calc_artifact_deps<'a>(
let mut maybe_non_artifact_lib = false;
let artifact_pkg = state.get(dep_id);
for dep in deps {
- let artifact = match dep.artifact() {
- Some(a) => a,
- None => {
- maybe_non_artifact_lib = true;
- continue;
- }
+ let Some(artifact) = dep.artifact() else {
+ maybe_non_artifact_lib = true;
+ continue;
};
has_artifact_lib |= artifact.is_lib();
// Custom build scripts (build/compile) never get artifact dependencies,
@@ -611,9 +607,8 @@ fn compute_deps_doc(
// the documentation of the library being built.
let mut ret = Vec::new();
for (id, deps) in state.deps(unit, unit_for) {
- let dep_lib = match calc_artifact_deps(unit, unit_for, id, &deps, state, &mut ret)? {
- Some(lib) => lib,
- None => continue,
+ let Some(dep_lib) = calc_artifact_deps(unit, unit_for, id, &deps, state, &mut ret)? else {
+ continue;
};
let dep_pkg = state.get(id);
// Rustdoc only needs rmeta files for regular dependencies.
@@ -923,9 +918,8 @@ fn connect_run_custom_build_deps(state: &mut State<'_, '_>) {
{
// This list of dependencies all depend on `unit`, an execution of
// the build script.
- let reverse_deps = match reverse_deps_map.get(unit) {
- Some(set) => set,
- None => continue,
+ let Some(reverse_deps) = reverse_deps_map.get(unit) else {
+ continue;
};
let to_add = reverse_deps
diff --git a/src/tools/cargo/src/cargo/core/dependency.rs b/src/tools/cargo/src/cargo/core/dependency.rs
index c8fee6262..f00bb0590 100644
--- a/src/tools/cargo/src/cargo/core/dependency.rs
+++ b/src/tools/cargo/src/cargo/core/dependency.rs
@@ -12,7 +12,6 @@ use crate::core::compiler::{CompileKind, CompileTarget};
use crate::core::{PackageId, SourceId, Summary};
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
-use crate::util::toml::StringOrVec;
use crate::util::OptVersionReq;
/// Information about a dependency requested by a Cargo manifest.
@@ -319,8 +318,8 @@ impl Dependency {
}
/// Sets the version requirement for this dependency.
- pub fn set_version_req(&mut self, req: VersionReq) -> &mut Dependency {
- Rc::make_mut(&mut self.inner).req = OptVersionReq::Req(req);
+ pub fn set_version_req(&mut self, req: OptVersionReq) -> &mut Dependency {
+ Rc::make_mut(&mut self.inner).req = req;
self
}
@@ -468,10 +467,7 @@ impl ser::Serialize for Artifact {
SerializedArtifact {
kinds: self.kinds(),
lib: self.is_lib,
- target: self.target.as_ref().map(|t| match t {
- ArtifactTarget::BuildDependencyAssumeTarget => "target",
- ArtifactTarget::Force(target) => target.rustc_target().as_str(),
- }),
+ target: self.target.as_ref().map(ArtifactTarget::as_str),
}
.serialize(s)
}
@@ -479,14 +475,14 @@ impl ser::Serialize for Artifact {
impl Artifact {
pub(crate) fn parse(
- artifacts: &StringOrVec,
+ artifacts: &[impl AsRef<str>],
is_lib: bool,
target: Option<&str>,
) -> CargoResult<Self> {
let kinds = ArtifactKind::validate(
artifacts
.iter()
- .map(|s| ArtifactKind::parse(s))
+ .map(|s| ArtifactKind::parse(s.as_ref()))
.collect::<Result<Vec<_>, _>>()?,
)?;
Ok(Artifact {
@@ -529,6 +525,13 @@ impl ArtifactTarget {
})
}
+ pub fn as_str(&self) -> &str {
+ match self {
+ ArtifactTarget::BuildDependencyAssumeTarget => "target",
+ ArtifactTarget::Force(target) => target.rustc_target().as_str(),
+ }
+ }
+
pub fn to_compile_kind(&self) -> Option<CompileKind> {
self.to_compile_target().map(CompileKind::Target)
}
@@ -539,6 +542,7 @@ impl ArtifactTarget {
ArtifactTarget::Force(target) => Some(*target),
}
}
+
pub(crate) fn to_resolved_compile_kind(
&self,
root_unit_compile_kind: CompileKind,
@@ -575,20 +579,13 @@ impl ser::Serialize for ArtifactKind {
where
S: ser::Serializer,
{
- let out: Cow<'_, str> = match *self {
- ArtifactKind::SelectedBinary(name) => format!("bin:{}", name.as_str()).into(),
- _ => self.crate_type().into(),
- };
- out.serialize(s)
+ self.as_str().serialize(s)
}
}
impl fmt::Display for ArtifactKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(match self {
- ArtifactKind::SelectedBinary(bin_name) => return write!(f, "bin:{bin_name}"),
- _ => self.crate_type(),
- })
+ f.write_str(&self.as_str())
}
}
@@ -604,7 +601,14 @@ impl ArtifactKind {
}
}
- fn parse(kind: &str) -> CargoResult<Self> {
+ pub fn as_str(&self) -> Cow<'static, str> {
+ match *self {
+ ArtifactKind::SelectedBinary(name) => format!("bin:{}", name.as_str()).into(),
+ _ => self.crate_type().into(),
+ }
+ }
+
+ pub fn parse(kind: &str) -> CargoResult<Self> {
Ok(match kind {
"bin" => ArtifactKind::AllBinaries,
"cdylib" => ArtifactKind::Cdylib,
diff --git a/src/tools/cargo/src/cargo/core/features.rs b/src/tools/cargo/src/cargo/core/features.rs
index 9b99d5a15..5faa2087e 100644
--- a/src/tools/cargo/src/cargo/core/features.rs
+++ b/src/tools/cargo/src/cargo/core/features.rs
@@ -518,9 +518,8 @@ impl Features {
) -> CargoResult<()> {
let nightly_features_allowed = self.nightly_features_allowed;
let is_local = self.is_local;
- let (slot, feature) = match self.status(feature_name) {
- Some(p) => p,
- None => bail!("unknown cargo feature `{}`", feature_name),
+ let Some((slot, feature)) = self.status(feature_name) else {
+ bail!("unknown cargo feature `{}`", feature_name)
};
if *slot {
@@ -531,15 +530,9 @@ impl Features {
}
let see_docs = || {
- let url_channel = match channel().as_str() {
- "dev" | "nightly" => "nightly/",
- "beta" => "beta/",
- _ => "",
- };
format!(
- "See https://doc.rust-lang.org/{}cargo/{} for more information \
- about using this feature.",
- url_channel, feature.docs
+ "See {} for more information about using this feature.",
+ cargo_docs_link(feature.docs)
)
};
@@ -718,6 +711,7 @@ unstable_cli_options!(
// All other unstable features.
// Please keep this list lexicographically ordered.
advanced_env: bool = (HIDDEN),
+ asymmetric_token: bool = ("Allows authenticating with asymmetric tokens"),
avoid_dev_deps: bool = ("Avoid installing dev-dependencies if possible"),
binary_dep_depinfo: bool = ("Track changes to dependency artifacts"),
bindeps: bool = ("Allow Cargo packages to depend on bin, cdylib, and staticlib crates, and use the artifacts built by those crates"),
@@ -728,7 +722,6 @@ unstable_cli_options!(
check_cfg: Option<(/*features:*/ bool, /*well_known_names:*/ bool, /*well_known_values:*/ bool, /*output:*/ bool)> = ("Specify scope of compile-time checking of `cfg` names/values"),
codegen_backend: bool = ("Enable the `codegen-backend` option in profiles in .cargo/config.toml file"),
config_include: bool = ("Enable the `include` key in config files"),
- credential_process: bool = ("Add a config setting to fetch registry authentication tokens by calling an external process"),
direct_minimal_versions: bool = ("Resolve minimal dependency versions instead of maximum (direct dependencies only)"),
doctest_xcompile: bool = ("Compile and run doctests for non-host target using runner config"),
dual_proc_macros: bool = ("Build proc-macros for both the host and the target"),
@@ -744,7 +737,6 @@ unstable_cli_options!(
panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"),
profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"),
publish_timeout: bool = ("Enable the `publish.timeout` key in .cargo/config.toml file"),
- registry_auth: bool = ("Authentication for alternative registries, and generate registry authentication tokens using asymmetric cryptography"),
rustdoc_map: bool = ("Allow passing external documentation mappings to rustdoc"),
rustdoc_scrape_examples: bool = ("Allows Rustdoc to scrape code examples from reverse-dependencies"),
script: bool = ("Enable support for single-file, `.rs` packages"),
@@ -818,13 +810,18 @@ const STABILIZED_TERMINAL_WIDTH: &str =
const STABILISED_SPARSE_REGISTRY: &str = "The sparse protocol is now the default for crates.io";
+const STABILIZED_CREDENTIAL_PROCESS: &str =
+ "Authentication with a credential provider is always available.";
+
+const STABILIZED_REGISTRY_AUTH: &str =
+ "Authenticated registries are available if a credential provider is configured.";
+
fn deserialize_build_std<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
where
D: serde::Deserializer<'de>,
{
- let crates = match <Option<Vec<String>>>::deserialize(deserializer)? {
- Some(list) => list,
- None => return Ok(None),
+ let Some(crates) = <Option<Vec<String>>>::deserialize(deserializer)? else {
+ return Ok(None);
};
let v = crates.join(",");
Ok(Some(
@@ -839,9 +836,8 @@ where
D: serde::Deserializer<'de>,
{
use serde::de::Error;
- let crates = match <Option<Vec<String>>>::deserialize(deserializer)? {
- Some(list) => list,
- None => return Ok(None),
+ let Some(crates) = <Option<Vec<String>>>::deserialize(deserializer)? else {
+ return Ok(None);
};
parse_check_cfg(crates.into_iter()).map_err(D::Error::custom)
@@ -1083,10 +1079,13 @@ impl CliUnstable {
"sparse-registry" => stabilized_warn(k, "1.68", STABILISED_SPARSE_REGISTRY),
"terminal-width" => stabilized_warn(k, "1.68", STABILIZED_TERMINAL_WIDTH),
"doctest-in-workspace" => stabilized_warn(k, "1.72", STABILIZED_DOCTEST_IN_WORKSPACE),
+ "credential-process" => stabilized_warn(k, "1.74", STABILIZED_CREDENTIAL_PROCESS),
+ "registry-auth" => stabilized_warn(k, "1.74", STABILIZED_REGISTRY_AUTH),
// Unstable features
// Sorted alphabetically:
"advanced-env" => self.advanced_env = parse_empty(k, v)?,
+ "asymmetric-token" => self.asymmetric_token = parse_empty(k, v)?,
"avoid-dev-deps" => self.avoid_dev_deps = parse_empty(k, v)?,
"binary-dep-depinfo" => self.binary_dep_depinfo = parse_empty(k, v)?,
"bindeps" => self.bindeps = parse_empty(k, v)?,
@@ -1099,7 +1098,6 @@ impl CliUnstable {
}
"codegen-backend" => self.codegen_backend = parse_empty(k, v)?,
"config-include" => self.config_include = parse_empty(k, v)?,
- "credential-process" => self.credential_process = parse_empty(k, v)?,
"direct-minimal-versions" => self.direct_minimal_versions = parse_empty(k, v)?,
"doctest-xcompile" => self.doctest_xcompile = parse_empty(k, v)?,
"dual-proc-macros" => self.dual_proc_macros = parse_empty(k, v)?,
@@ -1120,7 +1118,6 @@ impl CliUnstable {
"panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?,
"profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?,
"publish-timeout" => self.publish_timeout = parse_empty(k, v)?,
- "registry-auth" => self.registry_auth = parse_empty(k, v)?,
"rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?,
"rustdoc-scrape-examples" => self.rustdoc_scrape_examples = parse_empty(k, v)?,
"separate-nightlies" => self.separate_nightlies = parse_empty(k, v)?,
@@ -1206,7 +1203,7 @@ pub fn channel() -> String {
if let Ok(override_channel) = env::var("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS") {
return override_channel;
}
- // ALLOWED: the process of rustc boostrapping reads this through
+ // ALLOWED: the process of rustc bootstrapping reads this through
// `std::env`. We should make the behavior consistent. Also, we
// don't advertise this for bypassing nightly.
#[allow(clippy::disallowed_methods)]
@@ -1228,3 +1225,14 @@ pub fn channel() -> String {
fn cargo_use_gitoxide_instead_of_git2() -> bool {
std::env::var_os("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2").map_or(false, |value| value == "1")
}
+
+/// Generate a link to Cargo documentation for the current release channel
+/// `path` is the URL component after `https://doc.rust-lang.org/{channel}/cargo/`
+pub fn cargo_docs_link(path: &str) -> String {
+ let url_channel = match channel().as_str() {
+ "dev" | "nightly" => "nightly/",
+ "beta" => "beta/",
+ _ => "",
+ };
+ format!("https://doc.rust-lang.org/{url_channel}cargo/{path}")
+}
diff --git a/src/tools/cargo/src/cargo/core/manifest.rs b/src/tools/cargo/src/cargo/core/manifest.rs
index 5d46a7e06..7886abec3 100644
--- a/src/tools/cargo/src/cargo/core/manifest.rs
+++ b/src/tools/cargo/src/cargo/core/manifest.rs
@@ -19,7 +19,7 @@ use crate::core::{Edition, Feature, Features, WorkspaceConfig};
use crate::util::errors::*;
use crate::util::interning::InternedString;
use crate::util::toml::{TomlManifest, TomlProfiles};
-use crate::util::{short_hash, Config, Filesystem};
+use crate::util::{short_hash, Config, Filesystem, RustVersion};
pub enum EitherManifest {
Real(Manifest),
@@ -58,7 +58,7 @@ pub struct Manifest {
original: Rc<TomlManifest>,
unstable_features: Features,
edition: Edition,
- rust_version: Option<String>,
+ rust_version: Option<RustVersion>,
im_a_teapot: Option<bool>,
default_run: Option<String>,
metabuild: Option<Vec<String>>,
@@ -112,7 +112,7 @@ pub struct ManifestMetadata {
pub documentation: Option<String>, // URL
pub badges: BTreeMap<String, BTreeMap<String, String>>,
pub links: Option<String>,
- pub rust_version: Option<String>,
+ pub rust_version: Option<RustVersion>,
}
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
@@ -401,7 +401,7 @@ impl Manifest {
workspace: WorkspaceConfig,
unstable_features: Features,
edition: Edition,
- rust_version: Option<String>,
+ rust_version: Option<RustVersion>,
im_a_teapot: Option<bool>,
default_run: Option<String>,
original: Rc<TomlManifest>,
@@ -570,8 +570,8 @@ impl Manifest {
self.edition
}
- pub fn rust_version(&self) -> Option<&str> {
- self.rust_version.as_deref()
+ pub fn rust_version(&self) -> Option<&RustVersion> {
+ self.rust_version.as_ref()
}
pub fn custom_metadata(&self) -> Option<&toml::Value> {
diff --git a/src/tools/cargo/src/cargo/core/mod.rs b/src/tools/cargo/src/cargo/core/mod.rs
index e36c678c4..9b56564a7 100644
--- a/src/tools/cargo/src/cargo/core/mod.rs
+++ b/src/tools/cargo/src/cargo/core/mod.rs
@@ -8,7 +8,7 @@ pub use self::package_id_spec::PackageIdSpec;
pub use self::registry::Registry;
pub use self::resolver::{Resolve, ResolveVersion};
pub use self::shell::{Shell, Verbosity};
-pub use self::source::{GitReference, QueryKind, Source, SourceId, SourceMap};
+pub use self::source_id::{GitReference, SourceId};
pub use self::summary::{FeatureMap, FeatureValue, Summary};
pub use self::workspace::{
find_workspace_root, resolve_relative_path, MaybePackage, Workspace, WorkspaceConfig,
@@ -27,6 +27,6 @@ pub mod profiles;
pub mod registry;
pub mod resolver;
pub mod shell;
-pub mod source;
+mod source_id;
pub mod summary;
mod workspace;
diff --git a/src/tools/cargo/src/cargo/core/package.rs b/src/tools/cargo/src/cargo/core/package.rs
index c84941462..76f6c405b 100644
--- a/src/tools/cargo/src/cargo/core/package.rs
+++ b/src/tools/cargo/src/cargo/core/package.rs
@@ -21,9 +21,9 @@ use crate::core::compiler::{CompileKind, RustcTargetData};
use crate::core::dependency::DepKind;
use crate::core::resolver::features::ForceAllTargets;
use crate::core::resolver::{HasDevUnits, Resolve};
-use crate::core::source::MaybePackage;
use crate::core::{Dependency, Manifest, PackageId, SourceId, Target};
-use crate::core::{SourceMap, Summary, Workspace};
+use crate::core::{Summary, Workspace};
+use crate::sources::source::{MaybePackage, SourceMap};
use crate::util::config::PackageCacheLock;
use crate::util::errors::{CargoResult, HttpNotSuccessful};
use crate::util::interning::InternedString;
@@ -31,6 +31,7 @@ use crate::util::network::http::http_handle_and_timeout;
use crate::util::network::http::HttpTimeout;
use crate::util::network::retry::{Retry, RetryResult};
use crate::util::network::sleep::SleepTracker;
+use crate::util::RustVersion;
use crate::util::{self, internal, Config, Progress, ProgressStyle};
pub const MANIFEST_PREAMBLE: &str = "\
@@ -103,7 +104,7 @@ pub struct SerializedPackage {
#[serde(skip_serializing_if = "Option::is_none")]
metabuild: Option<Vec<String>>,
default_run: Option<String>,
- rust_version: Option<String>,
+ rust_version: Option<RustVersion>,
}
impl Package {
@@ -177,7 +178,7 @@ impl Package {
self.targets().iter().any(|target| target.proc_macro())
}
/// Gets the package's minimum Rust version.
- pub fn rust_version(&self) -> Option<&str> {
+ pub fn rust_version(&self) -> Option<&RustVersion> {
self.manifest().rust_version()
}
@@ -262,7 +263,7 @@ impl Package {
metabuild: self.manifest().metabuild().cloned(),
publish: self.publish().as_ref().cloned(),
default_run: self.manifest().default_run().map(|s| s.to_owned()),
- rust_version: self.rust_version().map(|s| s.to_owned()),
+ rust_version: self.rust_version().cloned(),
}
}
}
@@ -337,7 +338,7 @@ pub struct Downloads<'a, 'cfg> {
/// Total bytes for all successfully downloaded packages.
downloaded_bytes: u64,
/// Size (in bytes) and package name of the largest downloaded package.
- largest: (u64, String),
+ largest: (u64, InternedString),
/// Time when downloading started.
start: Instant,
/// Indicates *all* downloads were successful.
@@ -458,7 +459,7 @@ impl<'cfg> PackageSet<'cfg> {
))),
downloads_finished: 0,
downloaded_bytes: 0,
- largest: (0, String::new()),
+ largest: (0, InternedString::new("")),
success: false,
updated_at: Cell::new(Instant::now()),
timeout,
@@ -711,7 +712,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
// happen during `wait_for_download`
let token = self.next;
self.next += 1;
- debug!("downloading {} as {}", id, token);
+ debug!(target: "network", "downloading {} as {}", id, token);
assert!(self.pending_ids.insert(id));
let (mut handle, _timeout) = http_handle_and_timeout(self.set.config)?;
@@ -730,7 +731,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
crate::try_old_curl_http2_pipewait!(self.set.multiplexing, handle);
handle.write_function(move |buf| {
- debug!("{} - {} bytes of data", token, buf.len());
+ debug!(target: "network", "{} - {} bytes of data", token, buf.len());
tls::with(|downloads| {
if let Some(downloads) = downloads {
downloads.pending[&token]
@@ -811,7 +812,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
let (dl, data) = loop {
assert_eq!(self.pending.len(), self.pending_ids.len());
let (token, result) = self.wait_for_curl()?;
- debug!("{} finished with {:?}", token, result);
+ debug!(target: "network", "{} finished with {:?}", token, result);
let (mut dl, handle) = self
.pending
@@ -872,7 +873,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
return Err(e.context(format!("failed to download from `{}`", dl.url)))
}
RetryResult::Retry(sleep) => {
- debug!("download retry {} for {sleep}ms", dl.url);
+ debug!(target: "network", "download retry {} for {sleep}ms", dl.url);
self.sleeping.push(sleep, (dl, handle));
}
}
@@ -890,7 +891,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
self.downloads_finished += 1;
self.downloaded_bytes += dl.total.get();
if dl.total.get() > self.largest.0 {
- self.largest = (dl.total.get(), dl.id.name().to_string());
+ self.largest = (dl.total.get(), dl.id.name());
}
// We're about to synchronously extract the crate below. While we're
@@ -968,7 +969,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
.perform()
.with_context(|| "failed to perform http requests")
})?;
- debug!("handles remaining: {}", n);
+ debug!(target: "network", "handles remaining: {}", n);
let results = &mut self.results;
let pending = &self.pending;
self.set.multi.messages(|msg| {
@@ -977,7 +978,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
if let Some(result) = msg.result_for(handle) {
results.push((token, result));
} else {
- debug!("message without a result (?)");
+ debug!(target: "network", "message without a result (?)");
}
});
@@ -987,7 +988,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
assert_ne!(self.remaining(), 0);
if self.pending.is_empty() {
let delay = self.sleeping.time_to_next().unwrap();
- debug!("sleeping main thread for {delay:?}");
+ debug!(target: "network", "sleeping main thread for {delay:?}");
std::thread::sleep(delay);
} else {
let min_timeout = Duration::new(1, 0);
diff --git a/src/tools/cargo/src/cargo/core/package_id.rs b/src/tools/cargo/src/cargo/core/package_id.rs
index e17a73e68..ca126172c 100644
--- a/src/tools/cargo/src/cargo/core/package_id.rs
+++ b/src/tools/cargo/src/cargo/core/package_id.rs
@@ -10,7 +10,7 @@ use std::sync::OnceLock;
use serde::de;
use serde::ser;
-use crate::core::source::SourceId;
+use crate::core::SourceId;
use crate::util::interning::InternedString;
use crate::util::{CargoResult, ToSemver};
@@ -85,14 +85,12 @@ impl<'de> de::Deserialize<'de> for PackageId {
let mut s = string.splitn(3, ' ');
let name = s.next().unwrap();
let name = InternedString::new(name);
- let version = match s.next() {
- Some(s) => s,
- None => return Err(de::Error::custom("invalid serialized PackageId")),
+ let Some(version) = s.next() else {
+ return Err(de::Error::custom("invalid serialized PackageId"));
};
let version = version.to_semver().map_err(de::Error::custom)?;
- let url = match s.next() {
- Some(s) => s,
- None => return Err(de::Error::custom("invalid serialized PackageId")),
+ let Some(url) = s.next() else {
+ return Err(de::Error::custom("invalid serialized PackageId"));
};
let url = if url.starts_with('(') && url.ends_with(')') {
&url[1..url.len() - 1]
@@ -238,7 +236,7 @@ impl fmt::Debug for PackageId {
#[cfg(test)]
mod tests {
use super::PackageId;
- use crate::core::source::SourceId;
+ use crate::core::SourceId;
use crate::sources::CRATES_IO_INDEX;
use crate::util::IntoUrl;
@@ -254,43 +252,6 @@ mod tests {
}
#[test]
- fn debug() {
- let loc = CRATES_IO_INDEX.into_url().unwrap();
- let pkg_id = PackageId::new("foo", "1.0.0", SourceId::for_registry(&loc).unwrap()).unwrap();
- assert_eq!(
- r#"PackageId { name: "foo", version: "1.0.0", source: "registry `crates-io`" }"#,
- format!("{:?}", pkg_id)
- );
-
- let expected = r#"
-PackageId {
- name: "foo",
- version: "1.0.0",
- source: "registry `crates-io`",
-}
-"#
- .trim();
-
- // Can be removed once trailing commas in Debug have reached the stable
- // channel.
- let expected_without_trailing_comma = r#"
-PackageId {
- name: "foo",
- version: "1.0.0",
- source: "registry `crates-io`"
-}
-"#
- .trim();
-
- let actual = format!("{:#?}", pkg_id);
- if actual.ends_with(",\n}") {
- assert_eq!(actual, expected);
- } else {
- assert_eq!(actual, expected_without_trailing_comma);
- }
- }
-
- #[test]
fn display() {
let loc = CRATES_IO_INDEX.into_url().unwrap();
let pkg_id = PackageId::new("foo", "1.0.0", SourceId::for_registry(&loc).unwrap()).unwrap();
diff --git a/src/tools/cargo/src/cargo/core/package_id_spec.rs b/src/tools/cargo/src/cargo/core/package_id_spec.rs
index 267ea3ffd..53d99b84b 100644
--- a/src/tools/cargo/src/cargo/core/package_id_spec.rs
+++ b/src/tools/cargo/src/cargo/core/package_id_spec.rs
@@ -10,7 +10,8 @@ use crate::core::PackageId;
use crate::util::edit_distance;
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
-use crate::util::{validate_package_name, IntoUrl, ToSemver};
+use crate::util::PartialVersion;
+use crate::util::{validate_package_name, IntoUrl};
/// Some or all of the data required to identify a package:
///
@@ -24,7 +25,7 @@ use crate::util::{validate_package_name, IntoUrl, ToSemver};
#[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
pub struct PackageIdSpec {
name: InternedString,
- version: Option<Version>,
+ version: Option<PartialVersion>,
url: Option<Url>,
}
@@ -70,7 +71,7 @@ impl PackageIdSpec {
let mut parts = spec.splitn(2, [':', '@']);
let name = parts.next().unwrap();
let version = match parts.next() {
- Some(version) => Some(version.to_semver()?),
+ Some(version) => Some(version.parse::<PartialVersion>()?),
None => None,
};
validate_package_name(name, "pkgid", "")?;
@@ -94,12 +95,12 @@ impl PackageIdSpec {
spec.query(i)
}
- /// Convert a `PackageId` to a `PackageIdSpec`, which will have both the `Version` and `Url`
+ /// Convert a `PackageId` to a `PackageIdSpec`, which will have both the `PartialVersion` and `Url`
/// fields filled in.
pub fn from_package_id(package_id: PackageId) -> PackageIdSpec {
PackageIdSpec {
name: package_id.name(),
- version: Some(package_id.version().clone()),
+ version: Some(package_id.version().clone().into()),
url: Some(package_id.source_id().url().clone()),
}
}
@@ -123,24 +124,20 @@ impl PackageIdSpec {
)
})?;
match frag {
- Some(fragment) => {
- let mut parts = fragment.splitn(2, [':', '@']);
- let name_or_version = parts.next().unwrap();
- match parts.next() {
- Some(part) => {
- let version = part.to_semver()?;
- (InternedString::new(name_or_version), Some(version))
- }
- None => {
- if name_or_version.chars().next().unwrap().is_alphabetic() {
- (InternedString::new(name_or_version), None)
- } else {
- let version = name_or_version.to_semver()?;
- (InternedString::new(path_name), Some(version))
- }
+ Some(fragment) => match fragment.split_once([':', '@']) {
+ Some((name, part)) => {
+ let version = part.parse::<PartialVersion>()?;
+ (InternedString::new(name), Some(version))
+ }
+ None => {
+ if fragment.chars().next().unwrap().is_alphabetic() {
+ (InternedString::new(&fragment), None)
+ } else {
+ let version = fragment.parse::<PartialVersion>()?;
+ (InternedString::new(path_name), Some(version))
}
}
- }
+ },
None => (InternedString::new(path_name), None),
}
};
@@ -155,7 +152,12 @@ impl PackageIdSpec {
self.name
}
- pub fn version(&self) -> Option<&Version> {
+ /// Full `semver::Version`, if present
+ pub fn version(&self) -> Option<Version> {
+ self.version.as_ref().and_then(|v| v.version())
+ }
+
+ pub fn partial_version(&self) -> Option<&PartialVersion> {
self.version.as_ref()
}
@@ -174,7 +176,7 @@ impl PackageIdSpec {
}
if let Some(ref v) = self.version {
- if v != package_id.version() {
+ if !v.matches(package_id.version()) {
return false;
}
}
@@ -193,55 +195,52 @@ impl PackageIdSpec {
{
let all_ids: Vec<_> = i.into_iter().collect();
let mut ids = all_ids.iter().copied().filter(|&id| self.matches(id));
- let ret = match ids.next() {
- Some(id) => id,
- None => {
- let mut suggestion = String::new();
- let try_spec = |spec: PackageIdSpec, suggestion: &mut String| {
- let try_matches: Vec<_> = all_ids
- .iter()
- .copied()
- .filter(|&id| spec.matches(id))
- .collect();
- if !try_matches.is_empty() {
- suggestion.push_str("\nDid you mean one of these?\n");
- minimize(suggestion, &try_matches, self);
- }
- };
- if self.url.is_some() {
- try_spec(
- PackageIdSpec {
- name: self.name,
- version: self.version.clone(),
- url: None,
- },
- &mut suggestion,
- );
- }
- if suggestion.is_empty() && self.version.is_some() {
- try_spec(
- PackageIdSpec {
- name: self.name,
- version: None,
- url: None,
- },
- &mut suggestion,
- );
+ let Some(ret) = ids.next() else {
+ let mut suggestion = String::new();
+ let try_spec = |spec: PackageIdSpec, suggestion: &mut String| {
+ let try_matches: Vec<_> = all_ids
+ .iter()
+ .copied()
+ .filter(|&id| spec.matches(id))
+ .collect();
+ if !try_matches.is_empty() {
+ suggestion.push_str("\nDid you mean one of these?\n");
+ minimize(suggestion, &try_matches, self);
}
- if suggestion.is_empty() {
- suggestion.push_str(&edit_distance::closest_msg(
- &self.name,
- all_ids.iter(),
- |id| id.name().as_str(),
- ));
- }
-
- bail!(
- "package ID specification `{}` did not match any packages{}",
- self,
- suggestion
+ };
+ if self.url.is_some() {
+ try_spec(
+ PackageIdSpec {
+ name: self.name,
+ version: self.version.clone(),
+ url: None,
+ },
+ &mut suggestion,
+ );
+ }
+ if suggestion.is_empty() && self.version.is_some() {
+ try_spec(
+ PackageIdSpec {
+ name: self.name,
+ version: None,
+ url: None,
+ },
+ &mut suggestion,
);
}
+ if suggestion.is_empty() {
+ suggestion.push_str(&edit_distance::closest_msg(
+ &self.name,
+ all_ids.iter(),
+ |id| id.name().as_str(),
+ ));
+ }
+
+ bail!(
+ "package ID specification `{}` did not match any packages{}",
+ self,
+ suggestion
+ );
};
return match ids.next() {
Some(other) => {
@@ -250,8 +249,8 @@ impl PackageIdSpec {
your project, and the specification \
`{}` is ambiguous.\n\
Please re-run this command \
- with `-p <spec>` where `<spec>` is one \
- of the following:",
+ with one of the following \
+ specifications:",
self.name(),
self
);
@@ -326,7 +325,6 @@ mod tests {
use super::PackageIdSpec;
use crate::core::{PackageId, SourceId};
use crate::util::interning::InternedString;
- use crate::util::ToSemver;
use url::Url;
#[test]
@@ -351,16 +349,25 @@ mod tests {
"https://crates.io/foo#1.2.3",
PackageIdSpec {
name: InternedString::new("foo"),
- version: Some("1.2.3".to_semver().unwrap()),
+ version: Some("1.2.3".parse().unwrap()),
url: Some(Url::parse("https://crates.io/foo").unwrap()),
},
"https://crates.io/foo#1.2.3",
);
ok(
+ "https://crates.io/foo#1.2",
+ PackageIdSpec {
+ name: InternedString::new("foo"),
+ version: Some("1.2".parse().unwrap()),
+ url: Some(Url::parse("https://crates.io/foo").unwrap()),
+ },
+ "https://crates.io/foo#1.2",
+ );
+ ok(
"https://crates.io/foo#bar:1.2.3",
PackageIdSpec {
name: InternedString::new("bar"),
- version: Some("1.2.3".to_semver().unwrap()),
+ version: Some("1.2.3".parse().unwrap()),
url: Some(Url::parse("https://crates.io/foo").unwrap()),
},
"https://crates.io/foo#bar@1.2.3",
@@ -369,12 +376,21 @@ mod tests {
"https://crates.io/foo#bar@1.2.3",
PackageIdSpec {
name: InternedString::new("bar"),
- version: Some("1.2.3".to_semver().unwrap()),
+ version: Some("1.2.3".parse().unwrap()),
url: Some(Url::parse("https://crates.io/foo").unwrap()),
},
"https://crates.io/foo#bar@1.2.3",
);
ok(
+ "https://crates.io/foo#bar@1.2",
+ PackageIdSpec {
+ name: InternedString::new("bar"),
+ version: Some("1.2".parse().unwrap()),
+ url: Some(Url::parse("https://crates.io/foo").unwrap()),
+ },
+ "https://crates.io/foo#bar@1.2",
+ );
+ ok(
"foo",
PackageIdSpec {
name: InternedString::new("foo"),
@@ -387,7 +403,7 @@ mod tests {
"foo:1.2.3",
PackageIdSpec {
name: InternedString::new("foo"),
- version: Some("1.2.3".to_semver().unwrap()),
+ version: Some("1.2.3".parse().unwrap()),
url: None,
},
"foo@1.2.3",
@@ -396,21 +412,29 @@ mod tests {
"foo@1.2.3",
PackageIdSpec {
name: InternedString::new("foo"),
- version: Some("1.2.3".to_semver().unwrap()),
+ version: Some("1.2.3".parse().unwrap()),
url: None,
},
"foo@1.2.3",
);
+ ok(
+ "foo@1.2",
+ PackageIdSpec {
+ name: InternedString::new("foo"),
+ version: Some("1.2".parse().unwrap()),
+ url: None,
+ },
+ "foo@1.2",
+ );
}
#[test]
fn bad_parsing() {
assert!(PackageIdSpec::parse("baz:").is_err());
assert!(PackageIdSpec::parse("baz:*").is_err());
- assert!(PackageIdSpec::parse("baz:1.0").is_err());
assert!(PackageIdSpec::parse("baz@").is_err());
assert!(PackageIdSpec::parse("baz@*").is_err());
- assert!(PackageIdSpec::parse("baz@1.0").is_err());
+ assert!(PackageIdSpec::parse("baz@^1.0").is_err());
assert!(PackageIdSpec::parse("https://baz:1.0").is_err());
assert!(PackageIdSpec::parse("https://#baz:1.0").is_err());
}
@@ -419,14 +443,50 @@ mod tests {
fn matching() {
let url = Url::parse("https://example.com").unwrap();
let sid = SourceId::for_registry(&url).unwrap();
- let foo = PackageId::new("foo", "1.2.3", sid).unwrap();
- let bar = PackageId::new("bar", "1.2.3", sid).unwrap();
+ let foo = PackageId::new("foo", "1.2.3", sid).unwrap();
assert!(PackageIdSpec::parse("foo").unwrap().matches(foo));
- assert!(!PackageIdSpec::parse("foo").unwrap().matches(bar));
+ assert!(!PackageIdSpec::parse("bar").unwrap().matches(foo));
assert!(PackageIdSpec::parse("foo:1.2.3").unwrap().matches(foo));
assert!(!PackageIdSpec::parse("foo:1.2.2").unwrap().matches(foo));
assert!(PackageIdSpec::parse("foo@1.2.3").unwrap().matches(foo));
assert!(!PackageIdSpec::parse("foo@1.2.2").unwrap().matches(foo));
+ assert!(PackageIdSpec::parse("foo@1.2").unwrap().matches(foo));
+
+ let meta = PackageId::new("meta", "1.2.3+hello", sid).unwrap();
+ assert!(PackageIdSpec::parse("meta").unwrap().matches(meta));
+ assert!(PackageIdSpec::parse("meta@1").unwrap().matches(meta));
+ assert!(PackageIdSpec::parse("meta@1.2").unwrap().matches(meta));
+ assert!(PackageIdSpec::parse("meta@1.2.3").unwrap().matches(meta));
+ assert!(!PackageIdSpec::parse("meta@1.2.3-alpha.0")
+ .unwrap()
+ .matches(meta));
+ assert!(PackageIdSpec::parse("meta@1.2.3+hello")
+ .unwrap()
+ .matches(meta));
+ assert!(!PackageIdSpec::parse("meta@1.2.3+bye")
+ .unwrap()
+ .matches(meta));
+
+ let pre = PackageId::new("pre", "1.2.3-alpha.0", sid).unwrap();
+ assert!(PackageIdSpec::parse("pre").unwrap().matches(pre));
+ assert!(!PackageIdSpec::parse("pre@1").unwrap().matches(pre));
+ assert!(!PackageIdSpec::parse("pre@1.2").unwrap().matches(pre));
+ assert!(!PackageIdSpec::parse("pre@1.2.3").unwrap().matches(pre));
+ assert!(PackageIdSpec::parse("pre@1.2.3-alpha.0")
+ .unwrap()
+ .matches(pre));
+ assert!(!PackageIdSpec::parse("pre@1.2.3-alpha.1")
+ .unwrap()
+ .matches(pre));
+ assert!(!PackageIdSpec::parse("pre@1.2.3-beta.0")
+ .unwrap()
+ .matches(pre));
+ assert!(!PackageIdSpec::parse("pre@1.2.3+hello")
+ .unwrap()
+ .matches(pre));
+ assert!(!PackageIdSpec::parse("pre@1.2.3-alpha.0+hello")
+ .unwrap()
+ .matches(pre));
}
}
diff --git a/src/tools/cargo/src/cargo/core/profiles.rs b/src/tools/cargo/src/cargo/core/profiles.rs
index 5c7d3e248..1ad9ed5f7 100644
--- a/src/tools/cargo/src/cargo/core/profiles.rs
+++ b/src/tools/cargo/src/cargo/core/profiles.rs
@@ -1205,9 +1205,8 @@ fn merge_config_profiles(
fn get_config_profile(ws: &Workspace<'_>, name: &str) -> CargoResult<Option<TomlProfile>> {
let profile: Option<config::Value<TomlProfile>> =
ws.config().get(&format!("profile.{}", name))?;
- let profile = match profile {
- Some(profile) => profile,
- None => return Ok(None),
+ let Some(profile) = profile else {
+ return Ok(None);
};
let mut warnings = Vec::new();
profile
@@ -1239,13 +1238,11 @@ fn validate_packages_unique(
name: &str,
toml: &Option<TomlProfile>,
) -> CargoResult<HashSet<PackageIdSpec>> {
- let toml = match toml {
- Some(ref toml) => toml,
- None => return Ok(HashSet::new()),
+ let Some(toml) = toml else {
+ return Ok(HashSet::new());
};
- let overrides = match toml.package.as_ref() {
- Some(overrides) => overrides,
- None => return Ok(HashSet::new()),
+ let Some(overrides) = toml.package.as_ref() else {
+ return Ok(HashSet::new());
};
// Verify that a package doesn't match multiple spec overrides.
let mut found = HashSet::new();
@@ -1297,9 +1294,8 @@ fn validate_packages_unmatched(
toml: &TomlProfile,
found: &HashSet<PackageIdSpec>,
) -> CargoResult<()> {
- let overrides = match toml.package.as_ref() {
- Some(overrides) => overrides,
- None => return Ok(()),
+ let Some(overrides) = toml.package.as_ref() else {
+ return Ok(());
};
// Verify every override matches at least one package.
diff --git a/src/tools/cargo/src/cargo/core/registry.rs b/src/tools/cargo/src/cargo/core/registry.rs
index da3d612d0..9a6a5a035 100644
--- a/src/tools/cargo/src/cargo/core/registry.rs
+++ b/src/tools/cargo/src/cargo/core/registry.rs
@@ -2,8 +2,11 @@ use std::collections::{HashMap, HashSet};
use std::task::{ready, Poll};
use crate::core::PackageSet;
-use crate::core::{Dependency, PackageId, QueryKind, Source, SourceId, SourceMap, Summary};
+use crate::core::{Dependency, PackageId, SourceId, Summary};
use crate::sources::config::SourceConfigMap;
+use crate::sources::source::QueryKind;
+use crate::sources::source::Source;
+use crate::sources::source::SourceMap;
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
use crate::util::{CanonicalUrl, Config};
@@ -396,7 +399,7 @@ impl<'cfg> PackageRegistry<'cfg> {
// Note that this is somewhat subtle where the list of `ids` for a
// canonical URL is extend with possibly two ids per summary. This is done
// to handle the transition from the v2->v3 lock file format where in
- // v2 DefeaultBranch was either DefaultBranch or Branch("master") for
+ // v2 DefaultBranch was either DefaultBranch or Branch("master") for
// git dependencies. In this case if `summary.package_id()` is
// Branch("master") then alt_package_id will be DefaultBranch. This
// signifies that there's a patch available for either of those
diff --git a/src/tools/cargo/src/cargo/core/resolver/dep_cache.rs b/src/tools/cargo/src/cargo/core/resolver/dep_cache.rs
index 997533014..9041c5b0f 100644
--- a/src/tools/cargo/src/cargo/core/resolver/dep_cache.rs
+++ b/src/tools/cargo/src/cargo/core/resolver/dep_cache.rs
@@ -16,11 +16,11 @@ use crate::core::resolver::{
ActivateError, ActivateResult, CliFeatures, RequestedFeatures, ResolveOpts, VersionOrdering,
VersionPreferences,
};
-use crate::core::{
- Dependency, FeatureValue, PackageId, PackageIdSpec, QueryKind, Registry, Summary,
-};
+use crate::core::{Dependency, FeatureValue, PackageId, PackageIdSpec, Registry, Summary};
+use crate::sources::source::QueryKind;
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
+use crate::util::RustVersion;
use anyhow::Context as _;
use std::collections::{BTreeSet, HashMap, HashSet};
@@ -36,6 +36,7 @@ pub struct RegistryQueryer<'a> {
/// versions first. That allows `cargo update -Z minimal-versions` which will
/// specify minimum dependency versions to be used.
minimal_versions: bool,
+ max_rust_version: Option<RustVersion>,
/// a cache of `Candidate`s that fulfil a `Dependency` (and whether `first_minimal_version`)
registry_cache: HashMap<(Dependency, bool), Poll<Rc<Vec<Summary>>>>,
/// a cache of `Dependency`s that are required for a `Summary`
@@ -57,12 +58,14 @@ impl<'a> RegistryQueryer<'a> {
replacements: &'a [(PackageIdSpec, Dependency)],
version_prefs: &'a VersionPreferences,
minimal_versions: bool,
+ max_rust_version: Option<&RustVersion>,
) -> Self {
RegistryQueryer {
registry,
replacements,
version_prefs,
minimal_versions,
+ max_rust_version: max_rust_version.cloned(),
registry_cache: HashMap::new(),
summary_cache: HashMap::new(),
used_replacements: HashMap::new(),
@@ -112,7 +115,10 @@ impl<'a> RegistryQueryer<'a> {
let mut ret = Vec::new();
let ready = self.registry.query(dep, QueryKind::Exact, &mut |s| {
- ret.push(s);
+ if self.max_rust_version.is_none() || s.rust_version() <= self.max_rust_version.as_ref()
+ {
+ ret.push(s);
+ }
})?;
if ready.is_pending() {
self.registry_cache
@@ -123,11 +129,10 @@ impl<'a> RegistryQueryer<'a> {
let mut potential_matches = self
.replacements
.iter()
- .filter(|&&(ref spec, _)| spec.matches(summary.package_id()));
+ .filter(|(spec, _)| spec.matches(summary.package_id()));
- let &(ref spec, ref dep) = match potential_matches.next() {
- None => continue,
- Some(replacement) => replacement,
+ let Some((spec, dep)) = potential_matches.next() else {
+ continue;
};
debug!(
"found an override for {} {}",
@@ -168,11 +173,20 @@ impl<'a> RegistryQueryer<'a> {
)));
}
- // The dependency should be hard-coded to have the same name and an
- // exact version requirement, so both of these assertions should
- // never fail.
- assert_eq!(s.version(), summary.version());
- assert_eq!(s.name(), summary.name());
+ assert_eq!(
+ s.name(),
+ summary.name(),
+ "dependency should be hard coded to have the same name"
+ );
+ if s.version() != summary.version() {
+ return Poll::Ready(Err(anyhow::anyhow!(
+ "replacement specification `{}` matched {} and tried to override it with {}\n\
+ avoid matching unrelated packages by being more specific",
+ spec,
+ summary.version(),
+ s.version(),
+ )));
+ }
let replace = if s.source_id() == summary.source_id() {
debug!("Preventing\n{:?}\nfrom replacing\n{:?}", summary, s);
@@ -183,7 +197,7 @@ impl<'a> RegistryQueryer<'a> {
let matched_spec = spec.clone();
// Make sure no duplicates
- if let Some(&(ref spec, _)) = potential_matches.next() {
+ if let Some((spec, _)) = potential_matches.next() {
return Poll::Ready(Err(anyhow::anyhow!(
"overlapping replacement specifications found:\n\n \
* {}\n * {}\n\nboth specifications match: {}",
@@ -273,7 +287,7 @@ impl<'a> RegistryQueryer<'a> {
// dependencies with more candidates. This way if the dependency with
// only one candidate can't be resolved we don't have to do a bunch of
// work before we figure that out.
- deps.sort_by_key(|&(_, ref a, _)| a.len());
+ deps.sort_by_key(|(_, a, _)| a.len());
let out = Rc::new((used_features, Rc::new(deps)));
@@ -476,9 +490,8 @@ impl Requirements<'_> {
return Ok(());
}
- let fvs = match self.summary.features().get(&feat) {
- Some(fvs) => fvs,
- None => return Err(RequirementError::MissingFeature(feat)),
+ let Some(fvs) = self.summary.features().get(&feat) else {
+ return Err(RequirementError::MissingFeature(feat));
};
for fv in fvs {
@@ -525,10 +538,9 @@ impl RequirementError {
summary.package_id(),
feat
)),
- Some(p) => ActivateError::Conflict(
- p,
- ConflictReason::MissingFeatures(feat.to_string()),
- ),
+ Some(p) => {
+ ActivateError::Conflict(p, ConflictReason::MissingFeatures(feat))
+ }
};
}
if deps.iter().any(|dep| dep.is_optional()) {
@@ -569,10 +581,9 @@ impl RequirementError {
)),
// This code path currently isn't used, since `foo/bar`
// and `dep:` syntax is not allowed in a dependency.
- Some(p) => ActivateError::Conflict(
- p,
- ConflictReason::MissingFeatures(dep_name.to_string()),
- ),
+ Some(p) => {
+ ActivateError::Conflict(p, ConflictReason::MissingFeatures(dep_name))
+ }
}
}
RequirementError::Cycle(feat) => ActivateError::Fatal(anyhow::format_err!(
diff --git a/src/tools/cargo/src/cargo/core/resolver/encode.rs b/src/tools/cargo/src/cargo/core/resolver/encode.rs
index 1ee0d23f4..7835c2219 100644
--- a/src/tools/cargo/src/cargo/core/resolver/encode.rs
+++ b/src/tools/cargo/src/cargo/core/resolver/encode.rs
@@ -299,14 +299,13 @@ impl EncodableResolve {
let mut g = Graph::new();
- for &(ref id, _) in live_pkgs.values() {
+ for (id, _) in live_pkgs.values() {
g.add(*id);
}
for &(ref id, pkg) in live_pkgs.values() {
- let deps = match pkg.dependencies {
- Some(ref deps) => deps,
- None => continue,
+ let Some(ref deps) = pkg.dependencies else {
+ continue;
};
for edge in deps.iter() {
@@ -338,13 +337,12 @@ impl EncodableResolve {
let mut to_remove = Vec::new();
for (k, v) in metadata.iter().filter(|p| p.0.starts_with(prefix)) {
to_remove.push(k.to_string());
- let k = &k[prefix.len()..];
+ let k = k.strip_prefix(prefix).unwrap();
let enc_id: EncodablePackageId = k
.parse()
.with_context(|| internal("invalid encoding of checksum in lockfile"))?;
- let id = match lookup_id(&enc_id) {
- Some(id) => id,
- _ => continue,
+ let Some(id) = lookup_id(&enc_id) else {
+ continue;
};
let v = if v == "<none>" {
@@ -437,7 +435,7 @@ fn build_path_deps(ws: &Workspace<'_>) -> CargoResult<HashMap<String, SourceId>>
build_dep(dep, ws, &mut ret, &mut visited);
}
}
- for &(_, ref dep) in ws.root_replace() {
+ for (_, dep) in ws.root_replace() {
build_dep(dep, ws, &mut ret, &mut visited);
}
@@ -468,10 +466,7 @@ fn build_path_deps(ws: &Workspace<'_>) -> CargoResult<HashMap<String, SourceId>>
Ok(p) => p.join("Cargo.toml"),
Err(_) => return,
};
- let pkg = match ws.load(&path) {
- Ok(p) => p,
- Err(_) => return,
- };
+ let Ok(pkg) = ws.load(&path) else { return };
ret.insert(pkg.name().to_string(), pkg.package_id().source_id());
visited.insert(pkg.package_id().source_id());
build_pkg(&pkg, ws, ret, visited);
@@ -601,8 +596,8 @@ impl FromStr for EncodablePackageId {
let version = s.next();
let source_id = match s.next() {
Some(s) => {
- if s.starts_with('(') && s.ends_with(')') {
- Some(SourceId::from_url(&s[1..s.len() - 1])?)
+ if let Some(s) = s.strip_prefix('(').and_then(|s| s.strip_suffix(')')) {
+ Some(SourceId::from_url(s)?)
} else {
anyhow::bail!("invalid serialized PackageId")
}
diff --git a/src/tools/cargo/src/cargo/core/resolver/errors.rs b/src/tools/cargo/src/cargo/core/resolver/errors.rs
index ca5c833f4..b57a7c3eb 100644
--- a/src/tools/cargo/src/cargo/core/resolver/errors.rs
+++ b/src/tools/cargo/src/cargo/core/resolver/errors.rs
@@ -1,9 +1,10 @@
use std::fmt;
use std::task::Poll;
-use crate::core::{Dependency, PackageId, QueryKind, Registry, Summary};
+use crate::core::{Dependency, PackageId, Registry, Summary};
+use crate::sources::source::QueryKind;
use crate::util::edit_distance::edit_distance;
-use crate::util::{Config, VersionExt};
+use crate::util::{Config, OptVersionReq, VersionExt};
use anyhow::Error;
use super::context::Context;
@@ -223,9 +224,8 @@ pub(super) fn activation_error(
// Maybe the user mistyped the ver_req? Like `dep="2"` when `dep="0.2"`
// was meant. So we re-query the registry with `dep="*"` so we can
// list a few versions that were actually found.
- let all_req = semver::VersionReq::parse("*").unwrap();
let mut new_dep = dep.clone();
- new_dep.set_version_req(all_req);
+ new_dep.set_version_req(OptVersionReq::Any);
let mut candidates = loop {
match registry.query_vec(&new_dep, QueryKind::Exact) {
@@ -240,127 +240,122 @@ pub(super) fn activation_error(
candidates.sort_unstable_by(|a, b| b.version().cmp(a.version()));
- let mut msg =
- if !candidates.is_empty() {
- let versions = {
- let mut versions = candidates
- .iter()
- .take(3)
- .map(|cand| cand.version().to_string())
- .collect::<Vec<_>>();
-
- if candidates.len() > 3 {
- versions.push("...".into());
- }
+ let mut msg = if !candidates.is_empty() {
+ let versions = {
+ let mut versions = candidates
+ .iter()
+ .take(3)
+ .map(|cand| cand.version().to_string())
+ .collect::<Vec<_>>();
- versions.join(", ")
- };
+ if candidates.len() > 3 {
+ versions.push("...".into());
+ }
- let locked_version = dep
- .version_req()
- .locked_version()
- .map(|v| format!(" (locked to {})", v))
- .unwrap_or_default();
+ versions.join(", ")
+ };
+
+ let locked_version = dep
+ .version_req()
+ .locked_version()
+ .map(|v| format!(" (locked to {})", v))
+ .unwrap_or_default();
+
+ let mut msg = format!(
+ "failed to select a version for the requirement `{} = \"{}\"`{}\n\
+ candidate versions found which didn't match: {}\n\
+ location searched: {}\n",
+ dep.package_name(),
+ dep.version_req(),
+ locked_version,
+ versions,
+ registry.describe_source(dep.source_id()),
+ );
+ msg.push_str("required by ");
+ msg.push_str(&describe_path_in_context(cx, &parent.package_id()));
- let mut msg = format!(
- "failed to select a version for the requirement `{} = \"{}\"`{}\n\
- candidate versions found which didn't match: {}\n\
- location searched: {}\n",
- dep.package_name(),
- dep.version_req(),
- locked_version,
- versions,
- registry.describe_source(dep.source_id()),
+ // If we have a pre-release candidate, then that may be what our user is looking for
+ if let Some(pre) = candidates.iter().find(|c| c.version().is_prerelease()) {
+ msg.push_str("\nif you are looking for the prerelease package it needs to be specified explicitly");
+ msg.push_str(&format!(
+ "\n {} = {{ version = \"{}\" }}",
+ pre.name(),
+ pre.version()
+ ));
+ }
+
+ // If we have a path dependency with a locked version, then this may
+ // indicate that we updated a sub-package and forgot to run `cargo
+ // update`. In this case try to print a helpful error!
+ if dep.source_id().is_path() && dep.version_req().is_locked() {
+ msg.push_str(
+ "\nconsider running `cargo update` to update \
+ a path dependency's locked version",
);
- msg.push_str("required by ");
- msg.push_str(&describe_path_in_context(cx, &parent.package_id()));
-
- // If we have a path dependency with a locked version, then this may
- // indicate that we updated a sub-package and forgot to run `cargo
- // update`. In this case try to print a helpful error!
- if dep.source_id().is_path() && dep.version_req().is_locked() {
- msg.push_str(
- "\nconsider running `cargo update` to update \
- a path dependency's locked version",
- );
- }
+ }
+
+ if registry.is_replaced(dep.source_id()) {
+ msg.push_str("\nperhaps a crate was updated and forgotten to be re-vendored?");
+ }
- if registry.is_replaced(dep.source_id()) {
- msg.push_str("\nperhaps a crate was updated and forgotten to be re-vendored?");
+ msg
+ } else {
+ // Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`
+ // was meant. So we try asking the registry for a `fuzzy` search for suggestions.
+ let mut candidates = loop {
+ match registry.query_vec(&new_dep, QueryKind::Fuzzy) {
+ Poll::Ready(Ok(candidates)) => break candidates,
+ Poll::Ready(Err(e)) => return to_resolve_err(e),
+ Poll::Pending => match registry.block_until_ready() {
+ Ok(()) => continue,
+ Err(e) => return to_resolve_err(e),
+ },
}
+ };
- msg
+ candidates.sort_unstable_by_key(|a| a.name());
+ candidates.dedup_by(|a, b| a.name() == b.name());
+ let mut candidates: Vec<_> = candidates
+ .iter()
+ .filter_map(|n| Some((edit_distance(&*new_dep.package_name(), &*n.name(), 3)?, n)))
+ .collect();
+ candidates.sort_by_key(|o| o.0);
+ let mut msg: String;
+ if candidates.is_empty() {
+ msg = format!("no matching package named `{}` found\n", dep.package_name());
} else {
- // Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`
- // was meant. So we try asking the registry for a `fuzzy` search for suggestions.
- let mut candidates = loop {
- match registry.query_vec(&new_dep, QueryKind::Fuzzy) {
- Poll::Ready(Ok(candidates)) => break candidates,
- Poll::Ready(Err(e)) => return to_resolve_err(e),
- Poll::Pending => match registry.block_until_ready() {
- Ok(()) => continue,
- Err(e) => return to_resolve_err(e),
- },
- }
- };
-
- candidates.sort_unstable_by_key(|a| a.name());
- candidates.dedup_by(|a, b| a.name() == b.name());
- let mut candidates: Vec<_> = candidates
+ msg = format!(
+ "no matching package found\nsearched package name: `{}`\n",
+ dep.package_name()
+ );
+ let mut names = candidates
.iter()
- .filter_map(|n| Some((edit_distance(&*new_dep.package_name(), &*n.name(), 3)?, n)))
- .collect();
- candidates.sort_by_key(|o| o.0);
- let mut msg: String;
- if candidates.is_empty() {
- msg = format!("no matching package named `{}` found\n", dep.package_name());
- } else {
- msg = format!(
- "no matching package found\nsearched package name: `{}`\n",
- dep.package_name()
- );
-
- // If dependency package name is equal to the name of the candidate here
- // it may be a prerelease package which hasn't been specified correctly
- if dep.package_name() == candidates[0].1.name()
- && candidates[0].1.package_id().version().is_prerelease()
- {
- msg.push_str("prerelease package needs to be specified explicitly\n");
- msg.push_str(&format!(
- "{name} = {{ version = \"{version}\" }}",
- name = candidates[0].1.name(),
- version = candidates[0].1.package_id().version()
- ));
- } else {
- let mut names = candidates
- .iter()
- .take(3)
- .map(|c| c.1.name().as_str())
- .collect::<Vec<_>>();
-
- if candidates.len() > 3 {
- names.push("...");
- }
- // Vertically align first suggestion with missing crate name
- // so a typo jumps out at you.
- msg.push_str("perhaps you meant: ");
- msg.push_str(&names.iter().enumerate().fold(
- String::default(),
- |acc, (i, el)| match i {
- 0 => acc + el,
- i if names.len() - 1 == i && candidates.len() <= 3 => acc + " or " + el,
- _ => acc + ", " + el,
- },
- ));
- }
- msg.push('\n');
+ .take(3)
+ .map(|c| c.1.name().as_str())
+ .collect::<Vec<_>>();
+
+ if candidates.len() > 3 {
+ names.push("...");
}
- msg.push_str(&format!("location searched: {}\n", dep.source_id()));
- msg.push_str("required by ");
- msg.push_str(&describe_path_in_context(cx, &parent.package_id()));
+ // Vertically align first suggestion with missing crate name
+ // so a typo jumps out at you.
+ msg.push_str("perhaps you meant: ");
+ msg.push_str(&names.iter().enumerate().fold(
+ String::default(),
+ |acc, (i, el)| match i {
+ 0 => acc + el,
+ i if names.len() - 1 == i && candidates.len() <= 3 => acc + " or " + el,
+ _ => acc + ", " + el,
+ },
+ ));
+ msg.push('\n');
+ }
+ msg.push_str(&format!("location searched: {}\n", dep.source_id()));
+ msg.push_str("required by ");
+ msg.push_str(&describe_path_in_context(cx, &parent.package_id()));
- msg
- };
+ msg
+ };
if let Some(config) = config {
if config.offline() {
diff --git a/src/tools/cargo/src/cargo/core/resolver/features.rs b/src/tools/cargo/src/cargo/core/resolver/features.rs
index 4518f9fe7..f1c2aebcc 100644
--- a/src/tools/cargo/src/cargo/core/resolver/features.rs
+++ b/src/tools/cargo/src/cargo/core/resolver/features.rs
@@ -45,7 +45,8 @@ use crate::core::resolver::{Resolve, ResolveBehavior};
use crate::core::{FeatureValue, PackageId, PackageIdSpec, PackageSet, Workspace};
use crate::util::interning::InternedString;
use crate::util::CargoResult;
-use anyhow::bail;
+use anyhow::{bail, Context};
+use itertools::Itertools;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::rc::Rc;
@@ -408,7 +409,7 @@ pub type DiffMap = BTreeMap<PackageFeaturesKey, BTreeSet<InternedString>>;
/// [module-level documentation]: crate::core::resolver::features
pub struct FeatureResolver<'a, 'cfg> {
ws: &'a Workspace<'cfg>,
- target_data: &'a RustcTargetData<'cfg>,
+ target_data: &'a mut RustcTargetData<'cfg>,
/// The platforms to build for, requested by the user.
requested_targets: &'a [CompileKind],
resolve: &'a Resolve,
@@ -445,7 +446,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
/// with the result.
pub fn resolve(
ws: &Workspace<'cfg>,
- target_data: &RustcTargetData<'cfg>,
+ target_data: &'a mut RustcTargetData<'cfg>,
resolve: &Resolve,
package_set: &'a PackageSet<'cfg>,
cli_features: &CliFeatures,
@@ -544,7 +545,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
// features that enable other features.
return Ok(());
}
- for (dep_pkg_id, deps) in self.deps(pkg_id, fk) {
+ for (dep_pkg_id, deps) in self.deps(pkg_id, fk)? {
for (dep, dep_fk) in deps {
if dep.is_optional() {
// Optional dependencies are enabled in `activate_fv` when
@@ -609,19 +610,16 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
}
let summary = self.resolve.summary(pkg_id);
let feature_map = summary.features();
- let fvs = match feature_map.get(&feature_to_enable) {
- Some(fvs) => fvs,
- None => {
- // TODO: this should only happen for optional dependencies.
- // Other cases should be validated by Summary's `build_feature_map`.
- // Figure out some way to validate this assumption.
- tracing::debug!(
- "pkg {:?} does not define feature {}",
- pkg_id,
- feature_to_enable
- );
- return Ok(());
- }
+ let Some(fvs) = feature_map.get(&feature_to_enable) else {
+ // TODO: this should only happen for optional dependencies.
+ // Other cases should be validated by Summary's `build_feature_map`.
+ // Figure out some way to validate this assumption.
+ tracing::debug!(
+ "pkg {:?} does not define feature {}",
+ pkg_id,
+ feature_to_enable
+ );
+ return Ok(());
};
for fv in fvs {
self.activate_fv(pkg_id, fk, fv)?;
@@ -647,7 +645,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
.deferred_weak_dependencies
.remove(&(pkg_id, fk, dep_name));
// Activate the optional dep.
- for (dep_pkg_id, deps) in self.deps(pkg_id, fk) {
+ for (dep_pkg_id, deps) in self.deps(pkg_id, fk)? {
for (dep, dep_fk) in deps {
if dep.name_in_toml() != dep_name {
continue;
@@ -681,7 +679,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
dep_feature: InternedString,
weak: bool,
) -> CargoResult<()> {
- for (dep_pkg_id, deps) in self.deps(pkg_id, fk) {
+ for (dep_pkg_id, deps) in self.deps(pkg_id, fk)? {
for (dep, dep_fk) in deps {
if dep.name_in_toml() != dep_name {
continue;
@@ -777,12 +775,17 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
/// Returns the dependencies for a package, filtering out inactive targets.
fn deps(
- &self,
+ &mut self,
pkg_id: PackageId,
fk: FeaturesFor,
- ) -> Vec<(PackageId, Vec<(&'a Dependency, FeaturesFor)>)> {
+ ) -> CargoResult<Vec<(PackageId, Vec<(&'a Dependency, FeaturesFor)>)>> {
// Helper for determining if a platform is activated.
- let platform_activated = |dep: &Dependency| -> bool {
+ fn platform_activated(
+ dep: &Dependency,
+ fk: FeaturesFor,
+ target_data: &RustcTargetData<'_>,
+ requested_targets: &[CompileKind],
+ ) -> bool {
// We always count platforms as activated if the target stems from an artifact
// dependency's target specification. This triggers in conjunction with
// `[target.'cfg(…)'.dependencies]` manifest sections.
@@ -791,18 +794,17 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
// We always care about build-dependencies, and they are always
// Host. If we are computing dependencies "for a build script",
// even normal dependencies are host-only.
- self.target_data
- .dep_platform_activated(dep, CompileKind::Host)
+ target_data.dep_platform_activated(dep, CompileKind::Host)
}
- (_, FeaturesFor::NormalOrDev) => self
- .requested_targets
+ (_, FeaturesFor::NormalOrDev) => requested_targets
.iter()
- .any(|kind| self.target_data.dep_platform_activated(dep, *kind)),
- (_, FeaturesFor::ArtifactDep(target)) => self
- .target_data
- .dep_platform_activated(dep, CompileKind::Target(target)),
+ .any(|kind| target_data.dep_platform_activated(dep, *kind)),
+ (_, FeaturesFor::ArtifactDep(target)) => {
+ target_data.dep_platform_activated(dep, CompileKind::Target(target))
+ }
}
- };
+ }
+
self.resolve
.deps(pkg_id)
.map(|(dep_id, deps)| {
@@ -811,7 +813,12 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
.filter(|dep| {
if dep.platform().is_some()
&& self.opts.ignore_inactive_targets
- && !platform_activated(dep)
+ && !platform_activated(
+ dep,
+ fk,
+ self.target_data,
+ self.requested_targets,
+ )
{
return false;
}
@@ -820,7 +827,9 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
}
true
})
- .flat_map(|dep| {
+ .collect_vec() // collect because the next closure mutably borrows `self.target_data`
+ .into_iter()
+ .map(|dep| {
// Each `dep`endency can be built for multiple targets. For one, it
// may be a library target which is built as initially configured
// by `fk`. If it appears as build dependency, it must be built
@@ -852,28 +861,52 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
};
// `artifact_target_keys` are produced to fulfil the needs of artifacts that have a target specification.
- let artifact_target_keys = dep.artifact().map(|artifact| {
- (
- artifact.is_lib(),
- artifact.target().map(|target| match target {
- ArtifactTarget::Force(target) => {
- vec![FeaturesFor::ArtifactDep(target)]
- }
- ArtifactTarget::BuildDependencyAssumeTarget => self
- .requested_targets
- .iter()
- .map(|kind| match kind {
- CompileKind::Host => {
- let host_triple = self.target_data.rustc.host;
- CompileTarget::new(&host_triple).unwrap()
- }
- CompileKind::Target(target) => *target,
+ let artifact_target_keys = dep
+ .artifact()
+ .map(|artifact| {
+ let host_triple = self.target_data.rustc.host;
+ // not all targets may be queried before resolution since artifact dependencies
+ // and per-pkg-targets are not immediately known.
+ let mut activate_target = |target| {
+ let name = dep.name_in_toml();
+ self.target_data
+ .merge_compile_kind(CompileKind::Target(target))
+ .with_context(|| format!("failed to determine target information for target `{target}`.\n \
+ Artifact dependency `{name}` in package `{pkg_id}` requires building for `{target}`", target = target.rustc_target()))
+ };
+ CargoResult::Ok((
+ artifact.is_lib(),
+ artifact
+ .target()
+ .map(|target| {
+ CargoResult::Ok(match target {
+ ArtifactTarget::Force(target) => {
+ activate_target(target)?;
+ vec![FeaturesFor::ArtifactDep(target)]
+ }
+ // FIXME: this needs to interact with the `default-target` and `forced-target` values
+ // of the dependency
+ ArtifactTarget::BuildDependencyAssumeTarget => self
+ .requested_targets
+ .iter()
+ .map(|kind| match kind {
+ CompileKind::Host => {
+ CompileTarget::new(&host_triple)
+ .unwrap()
+ }
+ CompileKind::Target(target) => *target,
+ })
+ .map(|target| {
+ activate_target(target)?;
+ Ok(FeaturesFor::ArtifactDep(target))
+ })
+ .collect::<CargoResult<_>>()?,
+ })
})
- .map(FeaturesFor::ArtifactDep)
- .collect(),
- }),
- )
- });
+ .transpose()?,
+ ))
+ })
+ .transpose()?;
let dep_fks = match artifact_target_keys {
// The artifact is also a library and does specify custom
@@ -893,12 +926,13 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
// Use the standard feature key without any alteration.
Some((_, None)) | None => vec![lib_fk],
};
- dep_fks.into_iter().map(move |dep_fk| (dep, dep_fk))
+ Ok(dep_fks.into_iter().map(move |dep_fk| (dep, dep_fk)))
})
- .collect::<Vec<_>>();
- (dep_id, deps)
+ .flatten_ok()
+ .collect::<CargoResult<Vec<_>>>()?;
+ Ok((dep_id, deps))
})
- .filter(|(_id, deps)| !deps.is_empty())
+ .filter(|res| res.as_ref().map_or(true, |(_id, deps)| !deps.is_empty()))
.collect()
}
diff --git a/src/tools/cargo/src/cargo/core/resolver/mod.rs b/src/tools/cargo/src/cargo/core/resolver/mod.rs
index e3da6fe5a..7d8e8acd4 100644
--- a/src/tools/cargo/src/cargo/core/resolver/mod.rs
+++ b/src/tools/cargo/src/cargo/core/resolver/mod.rs
@@ -71,6 +71,7 @@ use crate::util::config::Config;
use crate::util::errors::CargoResult;
use crate::util::network::PollExt;
use crate::util::profile;
+use crate::util::RustVersion;
use self::context::Context;
use self::dep_cache::RegistryQueryer;
@@ -138,6 +139,7 @@ pub fn resolve(
version_prefs: &VersionPreferences,
config: Option<&Config>,
check_public_visible_dependencies: bool,
+ mut max_rust_version: Option<&RustVersion>,
) -> CargoResult<Resolve> {
let _p = profile::start("resolving");
let minimal_versions = match config {
@@ -148,8 +150,19 @@ pub fn resolve(
Some(config) => config.cli_unstable().direct_minimal_versions,
None => false,
};
- let mut registry =
- RegistryQueryer::new(registry, replacements, version_prefs, minimal_versions);
+ if !config
+ .map(|c| c.cli_unstable().msrv_policy)
+ .unwrap_or(false)
+ {
+ max_rust_version = None;
+ }
+ let mut registry = RegistryQueryer::new(
+ registry,
+ replacements,
+ version_prefs,
+ minimal_versions,
+ max_rust_version,
+ );
let cx = loop {
let cx = Context::new(check_public_visible_dependencies);
let cx = activate_deps_loop(
@@ -221,7 +234,7 @@ fn activate_deps_loop(
let mut past_conflicting_activations = conflict_cache::ConflictCache::new();
// Activate all the initial summaries to kick off some work.
- for &(ref summary, ref opts) in summaries {
+ for (summary, opts) in summaries {
debug!("initial activation: {}", summary.package_id());
let res = activate(
&mut cx,
@@ -501,9 +514,7 @@ fn activate_deps_loop(
if let Some((other_parent, conflict)) = remaining_deps
.iter()
// for deps related to us
- .filter(|&(_, ref other_dep)| {
- known_related_bad_deps.contains(other_dep)
- })
+ .filter(|(_, other_dep)| known_related_bad_deps.contains(other_dep))
.filter_map(|(other_parent, other_dep)| {
past_conflicting_activations
.find_conflicting(&cx, &other_dep, Some(pid))
@@ -1018,9 +1029,8 @@ fn find_candidate(
&frame.dep,
frame.parent.package_id(),
);
- let (candidate, has_another) = match next {
- Some(pair) => pair,
- None => continue,
+ let Some((candidate, has_another)) = next else {
+ continue;
};
// If all members of `conflicting_activations` are still
diff --git a/src/tools/cargo/src/cargo/core/resolver/types.rs b/src/tools/cargo/src/cargo/core/resolver/types.rs
index 40bdb6c21..9ef78090e 100644
--- a/src/tools/cargo/src/cargo/core/resolver/types.rs
+++ b/src/tools/cargo/src/cargo/core/resolver/types.rs
@@ -285,7 +285,7 @@ pub enum ConflictReason {
/// A dependency listed features that weren't actually available on the
/// candidate. For example we tried to activate feature `foo` but the
/// candidate we're activating didn't actually have the feature `foo`.
- MissingFeatures(String),
+ MissingFeatures(InternedString),
/// A dependency listed a feature that ended up being a required dependency.
/// For example we tried to activate feature `foo` but the
diff --git a/src/tools/cargo/src/cargo/core/resolver/version_prefs.rs b/src/tools/cargo/src/cargo/core/resolver/version_prefs.rs
index bf26d0498..28de77f11 100644
--- a/src/tools/cargo/src/cargo/core/resolver/version_prefs.rs
+++ b/src/tools/cargo/src/cargo/core/resolver/version_prefs.rs
@@ -81,6 +81,7 @@ impl VersionPreferences {
mod test {
use super::*;
use crate::core::SourceId;
+ use crate::util::RustVersion;
use std::collections::BTreeMap;
fn pkgid(name: &str, version: &str) -> PackageId {
@@ -103,7 +104,7 @@ mod test {
Vec::new(),
&features,
None::<&String>,
- None::<&String>,
+ None::<RustVersion>,
)
.unwrap()
}
diff --git a/src/tools/cargo/src/cargo/core/shell.rs b/src/tools/cargo/src/cargo/core/shell.rs
index 4d45e6098..a9b9e84af 100644
--- a/src/tools/cargo/src/cargo/core/shell.rs
+++ b/src/tools/cargo/src/cargo/core/shell.rs
@@ -2,10 +2,11 @@ use std::fmt;
use std::io::prelude::*;
use std::io::IsTerminal;
-use termcolor::Color::{Cyan, Green, Red, Yellow};
-use termcolor::{self, Color, ColorSpec, StandardStream, WriteColor};
+use anstream::AutoStream;
+use anstyle::Style;
use crate::util::errors::CargoResult;
+use crate::util::style::*;
pub enum TtyWidth {
NoTty,
@@ -77,11 +78,11 @@ impl fmt::Debug for Shell {
/// A `Write`able object, either with or without color support
enum ShellOut {
/// A plain write object without color support
- Write(Box<dyn Write>),
+ Write(AutoStream<Box<dyn Write>>),
/// Color-enabled stdio, with information on whether color should be used
Stream {
- stdout: StandardStream,
- stderr: StandardStream,
+ stdout: AutoStream<std::io::Stdout>,
+ stderr: AutoStream<std::io::Stderr>,
stderr_tty: bool,
color_choice: ColorChoice,
},
@@ -103,11 +104,13 @@ impl Shell {
/// output.
pub fn new() -> Shell {
let auto_clr = ColorChoice::CargoAuto;
+ let stdout_choice = auto_clr.to_anstream_color_choice();
+ let stderr_choice = auto_clr.to_anstream_color_choice();
Shell {
output: ShellOut::Stream {
- stdout: StandardStream::stdout(auto_clr.to_termcolor_color_choice(Stream::Stdout)),
- stderr: StandardStream::stderr(auto_clr.to_termcolor_color_choice(Stream::Stderr)),
- color_choice: ColorChoice::CargoAuto,
+ stdout: AutoStream::new(std::io::stdout(), stdout_choice),
+ stderr: AutoStream::new(std::io::stderr(), stderr_choice),
+ color_choice: auto_clr,
stderr_tty: std::io::stderr().is_terminal(),
},
verbosity: Verbosity::Verbose,
@@ -118,7 +121,7 @@ impl Shell {
/// Creates a shell from a plain writable object, with no color, and max verbosity.
pub fn from_write(out: Box<dyn Write>) -> Shell {
Shell {
- output: ShellOut::Write(out),
+ output: ShellOut::Write(AutoStream::never(out)), // strip all formatting on write
verbosity: Verbosity::Verbose,
needs_clear: false,
}
@@ -130,7 +133,7 @@ impl Shell {
&mut self,
status: &dyn fmt::Display,
message: Option<&dyn fmt::Display>,
- color: Color,
+ color: &Style,
justified: bool,
) -> CargoResult<()> {
match self.verbosity {
@@ -203,14 +206,14 @@ impl Shell {
T: fmt::Display,
U: fmt::Display,
{
- self.print(&status, Some(&message), Green, true)
+ self.print(&status, Some(&message), &HEADER, true)
}
pub fn status_header<T>(&mut self, status: T) -> CargoResult<()>
where
T: fmt::Display,
{
- self.print(&status, None, Cyan, true)
+ self.print(&status, None, &NOTE, true)
}
/// Shortcut to right-align a status message.
@@ -218,7 +221,7 @@ impl Shell {
&mut self,
status: T,
message: U,
- color: Color,
+ color: &Style,
) -> CargoResult<()>
where
T: fmt::Display,
@@ -255,20 +258,20 @@ impl Shell {
self.err_erase_line();
}
self.output
- .message_stderr(&"error", Some(&message), Red, false)
+ .message_stderr(&"error", Some(&message), &ERROR, false)
}
/// Prints an amber 'warning' message.
pub fn warn<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
match self.verbosity {
Verbosity::Quiet => Ok(()),
- _ => self.print(&"warning", Some(&message), Yellow, false),
+ _ => self.print(&"warning", Some(&message), &WARN, false),
}
}
/// Prints a cyan 'note' message.
pub fn note<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
- self.print(&"note", Some(&message), Cyan, false)
+ self.print(&"note", Some(&message), &NOTE, false)
}
/// Updates the verbosity of the shell.
@@ -303,8 +306,10 @@ impl Shell {
),
};
*color_choice = cfg;
- *stdout = StandardStream::stdout(cfg.to_termcolor_color_choice(Stream::Stdout));
- *stderr = StandardStream::stderr(cfg.to_termcolor_color_choice(Stream::Stderr));
+ let stdout_choice = cfg.to_anstream_color_choice();
+ let stderr_choice = cfg.to_anstream_color_choice();
+ *stdout = AutoStream::new(std::io::stdout(), stdout_choice);
+ *stderr = AutoStream::new(std::io::stderr(), stderr_choice);
}
Ok(())
}
@@ -324,36 +329,28 @@ impl Shell {
pub fn err_supports_color(&self) -> bool {
match &self.output {
ShellOut::Write(_) => false,
- ShellOut::Stream { stderr, .. } => stderr.supports_color(),
+ ShellOut::Stream { stderr, .. } => supports_color(stderr.current_choice()),
}
}
pub fn out_supports_color(&self) -> bool {
match &self.output {
ShellOut::Write(_) => false,
- ShellOut::Stream { stdout, .. } => stdout.supports_color(),
+ ShellOut::Stream { stdout, .. } => supports_color(stdout.current_choice()),
}
}
/// Write a styled fragment
///
/// Caller is responsible for deciding whether [`Shell::verbosity`] is affects output.
- pub fn write_stdout(
- &mut self,
- fragment: impl fmt::Display,
- color: &ColorSpec,
- ) -> CargoResult<()> {
+ pub fn write_stdout(&mut self, fragment: impl fmt::Display, color: &Style) -> CargoResult<()> {
self.output.write_stdout(fragment, color)
}
/// Write a styled fragment
///
/// Caller is responsible for deciding whether [`Shell::verbosity`] is affects output.
- pub fn write_stderr(
- &mut self,
- fragment: impl fmt::Display,
- color: &ColorSpec,
- ) -> CargoResult<()> {
+ pub fn write_stderr(&mut self, fragment: impl fmt::Display, color: &Style) -> CargoResult<()> {
self.output.write_stderr(fragment, color)
}
@@ -362,13 +359,6 @@ impl Shell {
if self.needs_clear {
self.err_erase_line();
}
- #[cfg(windows)]
- {
- if let ShellOut::Stream { stderr, .. } = &mut self.output {
- ::fwdansi::write_ansi(stderr, message)?;
- return Ok(());
- }
- }
self.err().write_all(message)?;
Ok(())
}
@@ -378,13 +368,6 @@ impl Shell {
if self.needs_clear {
self.err_erase_line();
}
- #[cfg(windows)]
- {
- if let ShellOut::Stream { stdout, .. } = &mut self.output {
- ::fwdansi::write_ansi(stdout, message)?;
- return Ok(());
- }
- }
self.out().write_all(message)?;
Ok(())
}
@@ -412,70 +395,46 @@ impl ShellOut {
&mut self,
status: &dyn fmt::Display,
message: Option<&dyn fmt::Display>,
- color: Color,
+ style: &Style,
justified: bool,
) -> CargoResult<()> {
- match *self {
- ShellOut::Stream { ref mut stderr, .. } => {
- stderr.reset()?;
- stderr.set_color(ColorSpec::new().set_bold(true).set_fg(Some(color)))?;
- if justified {
- write!(stderr, "{:>12}", status)?;
- } else {
- write!(stderr, "{}", status)?;
- stderr.set_color(ColorSpec::new().set_bold(true))?;
- write!(stderr, ":")?;
- }
- stderr.reset()?;
- match message {
- Some(message) => writeln!(stderr, " {}", message)?,
- None => write!(stderr, " ")?,
- }
- }
- ShellOut::Write(ref mut w) => {
- if justified {
- write!(w, "{:>12}", status)?;
- } else {
- write!(w, "{}:", status)?;
- }
- match message {
- Some(message) => writeln!(w, " {}", message)?,
- None => write!(w, " ")?,
- }
- }
+ let style = style.render();
+ let bold = (anstyle::Style::new() | anstyle::Effects::BOLD).render();
+ let reset = anstyle::Reset.render();
+
+ let mut buffer = Vec::new();
+ if justified {
+ write!(&mut buffer, "{style}{status:>12}{reset}")?;
+ } else {
+ write!(&mut buffer, "{style}{status}{reset}{bold}:{reset}")?;
}
+ match message {
+ Some(message) => writeln!(buffer, " {message}")?,
+ None => write!(buffer, " ")?,
+ }
+ self.stderr().write_all(&buffer)?;
Ok(())
}
/// Write a styled fragment
- fn write_stdout(&mut self, fragment: impl fmt::Display, color: &ColorSpec) -> CargoResult<()> {
- match *self {
- ShellOut::Stream { ref mut stdout, .. } => {
- stdout.reset()?;
- stdout.set_color(&color)?;
- write!(stdout, "{}", fragment)?;
- stdout.reset()?;
- }
- ShellOut::Write(ref mut w) => {
- write!(w, "{}", fragment)?;
- }
- }
+ fn write_stdout(&mut self, fragment: impl fmt::Display, style: &Style) -> CargoResult<()> {
+ let style = style.render();
+ let reset = anstyle::Reset.render();
+
+ let mut buffer = Vec::new();
+ write!(buffer, "{style}{}{reset}", fragment)?;
+ self.stdout().write_all(&buffer)?;
Ok(())
}
/// Write a styled fragment
- fn write_stderr(&mut self, fragment: impl fmt::Display, color: &ColorSpec) -> CargoResult<()> {
- match *self {
- ShellOut::Stream { ref mut stderr, .. } => {
- stderr.reset()?;
- stderr.set_color(&color)?;
- write!(stderr, "{}", fragment)?;
- stderr.reset()?;
- }
- ShellOut::Write(ref mut w) => {
- write!(w, "{}", fragment)?;
- }
- }
+ fn write_stderr(&mut self, fragment: impl fmt::Display, style: &Style) -> CargoResult<()> {
+ let style = style.render();
+ let reset = anstyle::Reset.render();
+
+ let mut buffer = Vec::new();
+ write!(buffer, "{style}{}{reset}", fragment)?;
+ self.stderr().write_all(&buffer)?;
Ok(())
}
@@ -497,33 +456,22 @@ impl ShellOut {
}
impl ColorChoice {
- /// Converts our color choice to termcolor's version.
- fn to_termcolor_color_choice(self, stream: Stream) -> termcolor::ColorChoice {
+ /// Converts our color choice to anstream's version.
+ fn to_anstream_color_choice(self) -> anstream::ColorChoice {
match self {
- ColorChoice::Always => termcolor::ColorChoice::Always,
- ColorChoice::Never => termcolor::ColorChoice::Never,
- ColorChoice::CargoAuto => {
- if stream.is_terminal() {
- termcolor::ColorChoice::Auto
- } else {
- termcolor::ColorChoice::Never
- }
- }
+ ColorChoice::Always => anstream::ColorChoice::Always,
+ ColorChoice::Never => anstream::ColorChoice::Never,
+ ColorChoice::CargoAuto => anstream::ColorChoice::Auto,
}
}
}
-enum Stream {
- Stdout,
- Stderr,
-}
-
-impl Stream {
- fn is_terminal(self) -> bool {
- match self {
- Self::Stdout => std::io::stdout().is_terminal(),
- Self::Stderr => std::io::stderr().is_terminal(),
- }
+fn supports_color(choice: anstream::ColorChoice) -> bool {
+ match choice {
+ anstream::ColorChoice::Always
+ | anstream::ColorChoice::AlwaysAnsi
+ | anstream::ColorChoice::Auto => true,
+ anstream::ColorChoice::Never => false,
}
}
diff --git a/src/tools/cargo/src/cargo/core/source/source_id.rs b/src/tools/cargo/src/cargo/core/source_id.rs
index 6bbc07a5d..d688b8739 100644
--- a/src/tools/cargo/src/cargo/core/source/source_id.rs
+++ b/src/tools/cargo/src/cargo/core/source_id.rs
@@ -1,8 +1,10 @@
use crate::core::PackageId;
use crate::sources::registry::CRATES_IO_HTTP_INDEX;
+use crate::sources::source::Source;
use crate::sources::{DirectorySource, CRATES_IO_DOMAIN, CRATES_IO_INDEX, CRATES_IO_REGISTRY};
use crate::sources::{GitSource, PathSource, RegistrySource};
-use crate::util::{config, CanonicalUrl, CargoResult, Config, IntoUrl};
+use crate::util::{config, CanonicalUrl, CargoResult, Config, IntoUrl, ToSemver};
+use anyhow::Context;
use serde::de;
use serde::ser;
use std::cmp::{self, Ordering};
@@ -28,9 +30,9 @@ static SOURCE_ID_CACHE: OnceLock<Mutex<HashSet<&'static SourceIdInner>>> = OnceL
/// `SourceId` is usually associated with an instance of [`Source`], which is
/// supposed to provide a `SourceId` via [`Source::source_id`] method.
///
-/// [`Source`]: super::Source
-/// [`Source::source_id`]: super::Source::source_id
-/// [`PackageId`]: super::super::PackageId
+/// [`Source`]: crate::sources::source::Source
+/// [`Source::source_id`]: crate::sources::source::Source::source_id
+/// [`PackageId`]: super::PackageId
#[derive(Clone, Copy, Eq, Debug)]
pub struct SourceId {
inner: &'static SourceIdInner,
@@ -49,14 +51,11 @@ struct SourceIdInner {
kind: SourceKind,
/// For example, the exact Git revision of the specified branch for a Git Source.
precise: Option<String>,
- /// Name of the registry source for alternative registries
- /// WARNING: this is not always set for alt-registries when the name is
- /// not known.
- name: Option<String>,
- /// Name of the alt registry in the `[registries]` table.
- /// WARNING: this is not always set for alt-registries when the name is
- /// not known.
- alt_registry_key: Option<String>,
+ /// Name of the remote registry.
+ ///
+ /// WARNING: this is not always set when the name is not known,
+ /// e.g. registry coming from `--index` or Cargo.lock
+ registry_key: Option<KeyOf>,
}
/// The possible kinds of code source.
@@ -91,11 +90,22 @@ pub enum GitReference {
DefaultBranch,
}
+/// Where the remote source key is defined.
+///
+/// The purpose of this is to provide better diagnostics for different sources of keys.
+#[derive(Debug, Clone, PartialEq, Eq)]
+enum KeyOf {
+ /// Defined in the `[registries]` table or the built-in `crates-io` key.
+ Registry(String),
+ /// Defined in the `[source]` replacement table.
+ Source(String),
+}
+
impl SourceId {
/// Creates a `SourceId` object from the kind and URL.
///
/// The canonical url will be calculated, but the precise field will not
- fn new(kind: SourceKind, url: Url, name: Option<&str>) -> CargoResult<SourceId> {
+ fn new(kind: SourceKind, url: Url, key: Option<KeyOf>) -> CargoResult<SourceId> {
if kind == SourceKind::SparseRegistry {
// Sparse URLs are different because they store the kind prefix (sparse+)
// in the URL. This is because the prefix is necessary to differentiate
@@ -109,8 +119,7 @@ impl SourceId {
canonical_url: CanonicalUrl::new(&url)?,
url,
precise: None,
- name: name.map(|n| n.into()),
- alt_registry_key: None,
+ registry_key: key,
});
Ok(source_id)
}
@@ -148,10 +157,8 @@ impl SourceId {
/// 656c58fb7c5ef5f12bc747f");
/// ```
pub fn from_url(string: &str) -> CargoResult<SourceId> {
- let mut parts = string.splitn(2, '+');
- let kind = parts.next().unwrap();
- let url = parts
- .next()
+ let (kind, url) = string
+ .split_once('+')
.ok_or_else(|| anyhow::format_err!("invalid source `{}`", string))?;
match kind {
@@ -230,10 +237,18 @@ impl SourceId {
SourceId::new(kind, url.to_owned(), None)
}
- /// Creates a `SourceId` from a remote registry URL with given name.
- pub fn for_alt_registry(url: &Url, name: &str) -> CargoResult<SourceId> {
+ /// Creates a `SourceId` for a remote registry from the `[registries]` table or crates.io.
+ pub fn for_alt_registry(url: &Url, key: &str) -> CargoResult<SourceId> {
let kind = Self::remote_source_kind(url);
- SourceId::new(kind, url.to_owned(), Some(name))
+ let key = KeyOf::Registry(key.into());
+ SourceId::new(kind, url.to_owned(), Some(key))
+ }
+
+ /// Creates a `SourceId` for a remote registry from the `[source]` replacement table.
+ pub fn for_source_replacement_registry(url: &Url, key: &str) -> CargoResult<SourceId> {
+ let kind = Self::remote_source_kind(url);
+ let key = KeyOf::Source(key.into());
+ SourceId::new(kind, url.to_owned(), Some(key))
}
/// Creates a `SourceId` from a local registry path.
@@ -253,11 +268,7 @@ impl SourceId {
/// This is the main cargo registry by default, but it can be overridden in
/// a `.cargo/config.toml`.
pub fn crates_io(config: &Config) -> CargoResult<SourceId> {
- config.crates_io_source_id(|| {
- config.check_registry_index_not_set()?;
- let url = CRATES_IO_INDEX.into_url().unwrap();
- SourceId::new(SourceKind::Registry, url, Some(CRATES_IO_REGISTRY))
- })
+ config.crates_io_source_id()
}
/// Returns the `SourceId` corresponding to the main repository, using the
@@ -266,7 +277,8 @@ impl SourceId {
if Self::crates_io_is_sparse(config)? {
config.check_registry_index_not_set()?;
let url = CRATES_IO_HTTP_INDEX.into_url().unwrap();
- SourceId::new(SourceKind::SparseRegistry, url, Some(CRATES_IO_REGISTRY))
+ let key = KeyOf::Registry(CRATES_IO_REGISTRY.into());
+ SourceId::new(SourceKind::SparseRegistry, url, Some(key))
} else {
Self::crates_io(config)
}
@@ -293,15 +305,7 @@ impl SourceId {
return Self::crates_io(config);
}
let url = config.get_registry_index(key)?;
- let kind = Self::remote_source_kind(&url);
- Ok(SourceId::wrap(SourceIdInner {
- kind,
- canonical_url: CanonicalUrl::new(&url)?,
- url,
- precise: None,
- name: Some(key.to_string()),
- alt_registry_key: Some(key.to_string()),
- }))
+ Self::for_alt_registry(&url, key)
}
/// Gets this source URL.
@@ -326,10 +330,8 @@ impl SourceId {
/// Displays the name of a registry if it has one. Otherwise just the URL.
pub fn display_registry_name(self) -> String {
- if self.is_crates_io() {
- CRATES_IO_REGISTRY.to_string()
- } else if let Some(name) = &self.inner.name {
- name.clone()
+ if let Some(key) = self.inner.registry_key.as_ref().map(|k| k.key()) {
+ key.into()
} else if self.precise().is_some() {
// We remove `precise` here to retrieve an permissive version of
// `SourceIdInner`, which may contain the registry name.
@@ -339,11 +341,10 @@ impl SourceId {
}
}
- /// Gets the name of the remote registry as defined in the `[registries]` table.
- /// WARNING: alt registries that come from Cargo.lock, or --index will
- /// not have a name.
+ /// Gets the name of the remote registry as defined in the `[registries]` table,
+ /// or the built-in `crates-io` key.
pub fn alt_registry_key(&self) -> Option<&str> {
- self.inner.alt_registry_key.as_deref()
+ self.inner.registry_key.as_ref()?.alternative_registry()
}
/// Returns `true` if this source is from a filesystem path.
@@ -396,25 +397,27 @@ impl SourceId {
self,
config: &'a Config,
yanked_whitelist: &HashSet<PackageId>,
- ) -> CargoResult<Box<dyn super::Source + 'a>> {
+ ) -> CargoResult<Box<dyn Source + 'a>> {
trace!("loading SourceId; {}", self);
match self.inner.kind {
SourceKind::Git(..) => Ok(Box::new(GitSource::new(self, config)?)),
SourceKind::Path => {
- let path = match self.inner.url.to_file_path() {
- Ok(p) => p,
- Err(()) => panic!("path sources cannot be remote"),
- };
+ let path = self
+ .inner
+ .url
+ .to_file_path()
+ .expect("path sources cannot be remote");
Ok(Box::new(PathSource::new(&path, self, config)))
}
SourceKind::Registry | SourceKind::SparseRegistry => Ok(Box::new(
RegistrySource::remote(self, yanked_whitelist, config)?,
)),
SourceKind::LocalRegistry => {
- let path = match self.inner.url.to_file_path() {
- Ok(p) => p,
- Err(()) => panic!("path sources cannot be remote"),
- };
+ let path = self
+ .inner
+ .url
+ .to_file_path()
+ .expect("path sources cannot be remote");
Ok(Box::new(RegistrySource::local(
self,
&path,
@@ -423,20 +426,16 @@ impl SourceId {
)))
}
SourceKind::Directory => {
- let path = match self.inner.url.to_file_path() {
- Ok(p) => p,
- Err(()) => panic!("path sources cannot be remote"),
- };
+ let path = self
+ .inner
+ .url
+ .to_file_path()
+ .expect("path sources cannot be remote");
Ok(Box::new(DirectorySource::new(&path, self, config)))
}
}
}
- /// Gets the value of the precise field.
- pub fn precise(self) -> Option<&'static str> {
- self.inner.precise.as_deref()
- }
-
/// Gets the Git reference if this is a git source, otherwise `None`.
pub fn git_reference(self) -> Option<&'static GitReference> {
match self.inner.kind {
@@ -445,6 +444,33 @@ impl SourceId {
}
}
+ /// Gets the value of the precise field.
+ pub fn precise(self) -> Option<&'static str> {
+ self.inner.precise.as_deref()
+ }
+
+ /// Check if the precise data field stores information for this `name`
+ /// from a call to [SourceId::with_precise_registry_version].
+ ///
+ /// If so return the version currently in the lock file and the version to be updated to.
+ /// If specified, our own source will have a precise version listed of the form
+ // `<pkg>=<p_req>-><f_req>` where `<pkg>` is the name of a crate on
+ // this source, `<p_req>` is the version installed and `<f_req>` is the
+ // version requested (argument to `--precise`).
+ pub fn precise_registry_version(
+ self,
+ name: &str,
+ ) -> Option<(semver::Version, semver::Version)> {
+ self.inner
+ .precise
+ .as_deref()
+ .and_then(|p| p.strip_prefix(name)?.strip_prefix('='))
+ .map(|p| {
+ let (current, requested) = p.split_once("->").unwrap();
+ (current.to_semver().unwrap(), requested.to_semver().unwrap())
+ })
+ }
+
/// Creates a new `SourceId` from this source with the given `precise`.
pub fn with_precise(self, v: Option<String>) -> SourceId {
SourceId::wrap(SourceIdInner {
@@ -453,6 +479,23 @@ impl SourceId {
})
}
+ /// When updating a lock file on a version using `cargo update --precise`
+ /// the requested version is stored in the precise field.
+ /// On a registry dependency we also need to keep track of the package that
+ /// should be updated and even which of the versions should be updated.
+ /// All of this gets encoded in the precise field using this method.
+ /// The data can be read with [SourceId::precise_registry_version]
+ pub fn with_precise_registry_version(
+ self,
+ name: impl fmt::Display,
+ version: &semver::Version,
+ precise: &str,
+ ) -> CargoResult<SourceId> {
+ semver::Version::parse(precise)
+ .with_context(|| format!("invalid version format for precise version `{precise}`"))?;
+ Ok(self.with_precise(Some(format!("{}={}->{}", name, version, precise))))
+ }
+
/// Returns `true` if the remote registry is the standard <https://crates.io>.
pub fn is_crates_io(self) -> bool {
match self.inner.kind {
@@ -614,10 +657,9 @@ impl Hash for SourceId {
/// The hash of `SourceIdInner` is used to retrieve its interned value from
/// `SOURCE_ID_CACHE`. We only care about fields that make `SourceIdInner`
/// unique. Optional fields not affecting the uniqueness must be excluded,
-/// such as [`name`] and [`alt_registry_key`]. That's why this is not derived.
+/// such as [`registry_key`]. That's why this is not derived.
///
-/// [`name`]: SourceIdInner::name
-/// [`alt_registry_key`]: SourceIdInner::alt_registry_key
+/// [`registry_key`]: SourceIdInner::registry_key
impl Hash for SourceIdInner {
fn hash<S: hash::Hasher>(&self, into: &mut S) {
self.kind.hash(into);
@@ -830,6 +872,23 @@ impl<'a> fmt::Display for PrettyRef<'a> {
}
}
+impl KeyOf {
+ /// Gets the underlying key.
+ fn key(&self) -> &str {
+ match self {
+ KeyOf::Registry(k) | KeyOf::Source(k) => k,
+ }
+ }
+
+ /// Gets the key if it's from an alternative registry.
+ fn alternative_registry(&self) -> Option<&str> {
+ match self {
+ KeyOf::Registry(k) => Some(k),
+ _ => None,
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::{GitReference, SourceId, SourceKind};
diff --git a/src/tools/cargo/src/cargo/core/summary.rs b/src/tools/cargo/src/cargo/core/summary.rs
index 1883df33b..128c0db9c 100644
--- a/src/tools/cargo/src/cargo/core/summary.rs
+++ b/src/tools/cargo/src/cargo/core/summary.rs
@@ -1,6 +1,7 @@
use crate::core::{Dependency, PackageId, SourceId};
use crate::util::interning::InternedString;
use crate::util::CargoResult;
+use crate::util::RustVersion;
use anyhow::bail;
use semver::Version;
use std::collections::{BTreeMap, HashMap, HashSet};
@@ -25,7 +26,7 @@ struct Inner {
features: Rc<FeatureMap>,
checksum: Option<String>,
links: Option<InternedString>,
- rust_version: Option<InternedString>,
+ rust_version: Option<RustVersion>,
}
impl Summary {
@@ -34,7 +35,7 @@ impl Summary {
dependencies: Vec<Dependency>,
features: &BTreeMap<InternedString, Vec<InternedString>>,
links: Option<impl Into<InternedString>>,
- rust_version: Option<impl Into<InternedString>>,
+ rust_version: Option<RustVersion>,
) -> CargoResult<Summary> {
// ****CAUTION**** If you change anything here that may raise a new
// error, be sure to coordinate that change with either the index
@@ -56,7 +57,7 @@ impl Summary {
features: Rc::new(feature_map),
checksum: None,
links: links.map(|l| l.into()),
- rust_version: rust_version.map(|l| l.into()),
+ rust_version,
}),
})
}
@@ -87,8 +88,8 @@ impl Summary {
self.inner.links
}
- pub fn rust_version(&self) -> Option<InternedString> {
- self.inner.rust_version
+ pub fn rust_version(&self) -> Option<&RustVersion> {
+ self.inner.rust_version.as_ref()
}
pub fn override_id(mut self, id: PackageId) -> Summary {
diff --git a/src/tools/cargo/src/cargo/core/workspace.rs b/src/tools/cargo/src/cargo/core/workspace.rs
index 9ee0cbe04..db379d780 100644
--- a/src/tools/cargo/src/cargo/core/workspace.rs
+++ b/src/tools/cargo/src/cargo/core/workspace.rs
@@ -23,6 +23,7 @@ use crate::util::edit_distance;
use crate::util::errors::{CargoResult, ManifestError};
use crate::util::interning::InternedString;
use crate::util::toml::{read_manifest, InheritableFields, TomlDependency, TomlProfiles};
+use crate::util::RustVersion;
use crate::util::{config::ConfigRelativePath, Config, Filesystem, IntoUrl};
use cargo_util::paths;
use cargo_util::paths::normalize_path;
@@ -509,7 +510,7 @@ impl<'cfg> Workspace<'cfg> {
self.members
.iter()
.filter_map(move |path| match packages.get(path) {
- &MaybePackage::Package(ref p) => Some(p),
+ MaybePackage::Package(p) => Some(p),
_ => None,
})
}
@@ -540,7 +541,7 @@ impl<'cfg> Workspace<'cfg> {
self.default_members
.iter()
.filter_map(move |path| match packages.get(path) {
- &MaybePackage::Package(ref p) => Some(p),
+ MaybePackage::Package(p) => Some(p),
_ => None,
})
}
@@ -595,6 +596,12 @@ impl<'cfg> Workspace<'cfg> {
self
}
+ /// Get the lowest-common denominator `package.rust-version` within the workspace, if specified
+ /// anywhere
+ pub fn rust_version(&self) -> Option<&RustVersion> {
+ self.members().filter_map(|pkg| pkg.rust_version()).min()
+ }
+
pub fn custom_metadata(&self) -> Option<&toml::Value> {
self.custom_metadata.as_ref()
}
@@ -656,18 +663,15 @@ impl<'cfg> Workspace<'cfg> {
/// will transitively follow all `path` dependencies looking for members of
/// the workspace.
fn find_members(&mut self) -> CargoResult<()> {
- let workspace_config = match self.load_workspace_config()? {
- Some(workspace_config) => workspace_config,
- None => {
- debug!("find_members - only me as a member");
- self.members.push(self.current_manifest.clone());
- self.default_members.push(self.current_manifest.clone());
- if let Ok(pkg) = self.current() {
- let id = pkg.package_id();
- self.member_ids.insert(id);
- }
- return Ok(());
+ let Some(workspace_config) = self.load_workspace_config()? else {
+ debug!("find_members - only me as a member");
+ self.members.push(self.current_manifest.clone());
+ self.default_members.push(self.current_manifest.clone());
+ if let Ok(pkg) = self.current() {
+ let id = pkg.package_id();
+ self.member_ids.insert(id);
}
+ return Ok(());
};
// self.root_manifest must be Some to have retrieved workspace_config
@@ -1021,11 +1025,18 @@ impl<'cfg> Workspace<'cfg> {
.max()
{
let resolver = edition.default_resolve_behavior().to_manifest();
- self.config.shell().warn(format_args!("some crates are on edition {edition} which defaults to `resolver = \"{resolver}\"`, but virtual workspaces default to `resolver = \"1\"`"))?;
+ self.config.shell().warn(format_args!(
+ "virtual workspace defaulting to `resolver = \"1\"` despite one or more workspace members being on edition {edition} which implies `resolver = \"{resolver}\"`"
+ ))?;
self.config.shell().note(
"to keep the current resolver, specify `workspace.resolver = \"1\"` in the workspace root's manifest",
)?;
- self.config.shell().note(format_args!("to use the edition {edition} resolver, specify `workspace.resolver = \"{resolver}\"` in the workspace root's manifest"))?;
+ self.config.shell().note(format_args!(
+ "to use the edition {edition} resolver, specify `workspace.resolver = \"{resolver}\"` in the workspace root's manifest"
+ ))?;
+ self.config.shell().note(
+ "for more details see https://doc.rust-lang.org/cargo/reference/resolver.html#resolver-versions",
+ )?;
}
}
}
@@ -1035,7 +1046,7 @@ impl<'cfg> Workspace<'cfg> {
pub fn load(&self, manifest_path: &Path) -> CargoResult<Package> {
match self.packages.maybe_get(manifest_path) {
- Some(&MaybePackage::Package(ref p)) => return Ok(p.clone()),
+ Some(MaybePackage::Package(p)) => return Ok(p.clone()),
Some(&MaybePackage::Virtual(_)) => bail!("cannot load workspace root"),
None => {}
}
@@ -1679,9 +1690,8 @@ impl WorkspaceRootConfig {
}
fn expand_member_path(path: &Path) -> CargoResult<Vec<PathBuf>> {
- let path = match path.to_str() {
- Some(p) => p,
- None => return Ok(Vec::new()),
+ let Some(path) = path.to_str() else {
+ return Ok(Vec::new());
};
let res = glob(path).with_context(|| format!("could not parse pattern `{}`", &path))?;
let res = res
diff --git a/src/tools/cargo/src/cargo/lib.rs b/src/tools/cargo/src/cargo/lib.rs
index 9f6edf80d..908ff4ecc 100644
--- a/src/tools/cargo/src/cargo/lib.rs
+++ b/src/tools/cargo/src/cargo/lib.rs
@@ -1,16 +1,3 @@
-// For various reasons, some idioms are still allow'ed, but we would like to
-// test and enforce them.
-#![warn(rust_2018_idioms)]
-// Due to some of the default clippy lints being somewhat subjective and not
-// necessarily an improvement, we prefer to not use them at this time.
-#![allow(clippy::all)]
-#![warn(clippy::disallowed_methods)]
-#![warn(clippy::self_named_module_files)]
-#![warn(clippy::print_stdout)]
-#![warn(clippy::print_stderr)]
-#![warn(clippy::dbg_macro)]
-#![allow(rustdoc::private_intra_doc_links)]
-
//! # Cargo as a library
//!
//! There are two places you can find API documentation of cargo-the-library,
@@ -20,7 +7,7 @@
//! - <https://doc.rust-lang.org/nightly/nightly-rustc/cargo>: targeted at cargo contributors
//! - Updated on each update of the `cargo` submodule in `rust-lang/rust`
//!
-//! **WARNING:** Using Cargo as a library has drawbacks, particulary the API is unstable,
+//! **WARNING:** Using Cargo as a library has drawbacks, particularly the API is unstable,
//! and there is no clear path to stabilize it soon at the time of writing. See [The Cargo Book:
//! External tools] for more on this topic.
//!
@@ -51,8 +38,8 @@
//! - [`core::compiler::fingerprint`]:
//! The `fingerprint` module contains all the code that handles detecting
//! if a crate needs to be recompiled.
-//! - [`core::source`]:
-//! The [`core::Source`] trait is an abstraction over different sources of packages.
+//! - [`sources::source`]:
+//! The [`sources::source::Source`] trait is an abstraction over different sources of packages.
//! Sources are uniquely identified by a [`core::SourceId`]. Sources are implemented in the [`sources`]
//! directory.
//! - [`util`]:
@@ -91,9 +78,7 @@
//! This is the `#[cargo_test]` proc-macro used by the test suite to define tests.
//! - [`credential`](https://github.com/rust-lang/cargo/tree/master/credential)
//! This subdirectory contains several packages for implementing the
-//! experimental
-//! [credential-process](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#credential-process)
-//! feature.
+//! [credential providers](https://doc.rust-lang.org/nightly/cargo/reference/registry-authentication.html).
//! - [`mdman`](https://github.com/rust-lang/cargo/tree/master/crates/mdman)
//! ([nightly docs](https://doc.rust-lang.org/nightly/nightly-rustc/mdman/index.html)):
//! This is a utility for generating cargo's man pages. See [Building the man
@@ -144,6 +129,20 @@
//! [The Cargo Book]: https://doc.rust-lang.org/cargo/
//! [Cargo Contributor Guide]: https://doc.crates.io/contrib/
+// TODO: consider removing these lint attributes when `-Zlints` hits stable.
+// For various reasons, some idioms are still allow'ed, but we would like to
+// test and enforce them.
+#![warn(rust_2018_idioms)]
+// Due to some of the default clippy lints being somewhat subjective and not
+// necessarily an improvement, we prefer to not use them at this time.
+#![allow(clippy::all)]
+#![warn(clippy::disallowed_methods)]
+#![warn(clippy::self_named_module_files)]
+#![warn(clippy::print_stdout)]
+#![warn(clippy::print_stderr)]
+#![warn(clippy::dbg_macro)]
+#![allow(rustdoc::private_intra_doc_links)]
+
use crate::core::shell::Verbosity::Verbose;
use crate::core::Shell;
use anyhow::Error;
diff --git a/src/tools/cargo/src/cargo/ops/cargo_add/mod.rs b/src/tools/cargo/src/cargo/ops/cargo_add/mod.rs
index 11ca282ee..968d6068f 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_add/mod.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_add/mod.rs
@@ -12,20 +12,18 @@ use anyhow::Context as _;
use cargo_util::paths;
use indexmap::IndexSet;
use itertools::Itertools;
-use termcolor::Color::Green;
-use termcolor::Color::Red;
-use termcolor::ColorSpec;
use toml_edit::Item as TomlItem;
use crate::core::dependency::DepKind;
use crate::core::registry::PackageRegistry;
use crate::core::FeatureValue;
use crate::core::Package;
-use crate::core::QueryKind;
use crate::core::Registry;
use crate::core::Shell;
use crate::core::Summary;
use crate::core::Workspace;
+use crate::sources::source::QueryKind;
+use crate::util::style;
use crate::util::toml_mut::dependency::Dependency;
use crate::util::toml_mut::dependency::GitSource;
use crate::util::toml_mut::dependency::MaybeWorkspace;
@@ -34,6 +32,7 @@ use crate::util::toml_mut::dependency::Source;
use crate::util::toml_mut::dependency::WorkspaceSource;
use crate::util::toml_mut::manifest::DepTable;
use crate::util::toml_mut::manifest::LocalManifest;
+use crate::util::RustVersion;
use crate::CargoResult;
use crate::Config;
use crate_spec::CrateSpec;
@@ -503,9 +502,7 @@ fn get_existing_dependency(
})
.collect();
possible.sort_by_key(|(key, _)| *key);
- let (key, dep) = if let Some(item) = possible.pop() {
- item
- } else {
+ let Some((key, dep)) = possible.pop() else {
return Ok(None);
};
let mut dep = dep?;
@@ -567,16 +564,7 @@ fn get_latest_dependency(
})?;
if config.cli_unstable().msrv_policy && honor_rust_version {
- fn parse_msrv(rust_version: impl AsRef<str>) -> (u64, u64, u64) {
- // HACK: `rust-version` is a subset of the `VersionReq` syntax that only ever
- // has one comparator with a required minor and optional patch, and uses no
- // other features. If in the future this syntax is expanded, this code will need
- // to be updated.
- let version_req = semver::VersionReq::parse(rust_version.as_ref()).unwrap();
- assert!(version_req.comparators.len() == 1);
- let comp = &version_req.comparators[0];
- assert_eq!(comp.op, semver::Op::Caret);
- assert_eq!(comp.pre, semver::Prerelease::EMPTY);
+ fn parse_msrv(comp: &RustVersion) -> (u64, u64, u64) {
(comp.major, comp.minor.unwrap_or(0), comp.patch.unwrap_or(0))
}
@@ -636,7 +624,7 @@ fn get_latest_dependency(
fn rust_version_incompat_error(
dep: &str,
- rust_version: &str,
+ rust_version: &RustVersion,
lowest_rust_version: Option<&Summary>,
) -> anyhow::Error {
let mut error_msg = format!(
@@ -955,51 +943,73 @@ fn print_dep_table_msg(shell: &mut Shell, dep: &DependencyUI) -> CargoResult<()>
if matches!(shell.verbosity(), crate::core::shell::Verbosity::Quiet) {
return Ok(());
}
+
let (activated, deactivated) = dep.features();
if !activated.is_empty() || !deactivated.is_empty() {
let prefix = format!("{:>13}", " ");
- let suffix = if let Some(version) = &dep.available_version {
- let mut version = version.clone();
- version.build = Default::default();
- let version = version.to_string();
- // Avoid displaying the version if it will visually look like the version req that we
- // showed earlier
- let version_req = dep
- .version()
- .and_then(|v| semver::VersionReq::parse(v).ok())
- .and_then(|v| precise_version(&v));
- if version_req.as_deref() != Some(version.as_str()) {
- format!(" as of v{version}")
- } else {
- "".to_owned()
+ let suffix = format_features_version_suffix(&dep);
+
+ shell.write_stderr(format_args!("{prefix}Features{suffix}:\n"), &style::NOP)?;
+
+ const MAX_FEATURE_PRINTS: usize = 30;
+ let total_activated = activated.len();
+ let total_deactivated = deactivated.len();
+
+ if total_activated <= MAX_FEATURE_PRINTS {
+ for feat in activated {
+ shell.write_stderr(&prefix, &style::NOP)?;
+ shell.write_stderr('+', &style::GOOD)?;
+ shell.write_stderr(format_args!(" {feat}\n"), &style::NOP)?;
}
} else {
- "".to_owned()
- };
- shell.write_stderr(
- format_args!("{}Features{}:\n", prefix, suffix),
- &ColorSpec::new(),
- )?;
- for feat in activated {
- shell.write_stderr(&prefix, &ColorSpec::new())?;
- shell.write_stderr('+', &ColorSpec::new().set_bold(true).set_fg(Some(Green)))?;
- shell.write_stderr(format_args!(" {}\n", feat), &ColorSpec::new())?;
+ shell.write_stderr(
+ format_args!("{prefix}{total_activated} activated features\n"),
+ &style::NOP,
+ )?;
}
- for feat in deactivated {
- shell.write_stderr(&prefix, &ColorSpec::new())?;
- shell.write_stderr('-', &ColorSpec::new().set_bold(true).set_fg(Some(Red)))?;
- shell.write_stderr(format_args!(" {}\n", feat), &ColorSpec::new())?;
+
+ if total_activated + total_deactivated <= MAX_FEATURE_PRINTS {
+ for feat in deactivated {
+ shell.write_stderr(&prefix, &style::NOP)?;
+ shell.write_stderr('-', &style::ERROR)?;
+ shell.write_stderr(format_args!(" {feat}\n"), &style::NOP)?;
+ }
+ } else {
+ shell.write_stderr(
+ format_args!("{prefix}{total_deactivated} deactivated features\n"),
+ &style::NOP,
+ )?;
}
}
Ok(())
}
+fn format_features_version_suffix(dep: &DependencyUI) -> String {
+ if let Some(version) = &dep.available_version {
+ let mut version = version.clone();
+ version.build = Default::default();
+ let version = version.to_string();
+ // Avoid displaying the version if it will visually look like the version req that we
+ // showed earlier
+ let version_req = dep
+ .version()
+ .and_then(|v| semver::VersionReq::parse(v).ok())
+ .and_then(|v| precise_version(&v));
+ if version_req.as_deref() != Some(version.as_str()) {
+ format!(" as of v{version}")
+ } else {
+ "".to_owned()
+ }
+ } else {
+ "".to_owned()
+ }
+}
+
// Based on Iterator::is_sorted from nightly std; remove in favor of that when stabilized.
fn is_sorted(mut it: impl Iterator<Item = impl PartialOrd>) -> bool {
- let mut last = match it.next() {
- Some(e) => e,
- None => return true,
+ let Some(mut last) = it.next() else {
+ return true;
};
for curr in it {
diff --git a/src/tools/cargo/src/cargo/ops/cargo_clean.rs b/src/tools/cargo/src/cargo/ops/cargo_clean.rs
index b9b33690e..6f58b8bdc 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_clean.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_clean.rs
@@ -5,15 +5,14 @@ use crate::ops;
use crate::util::edit_distance;
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
-use crate::util::{Config, Progress, ProgressStyle};
-
-use anyhow::Context as _;
+use crate::util::{human_readable_bytes, Config, Progress, ProgressStyle};
+use anyhow::bail;
use cargo_util::paths;
use std::fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
-pub struct CleanOptions<'a> {
- pub config: &'a Config,
+pub struct CleanOptions<'cfg> {
+ pub config: &'cfg Config,
/// A list of packages to clean. If empty, everything is cleaned.
pub spec: Vec<String>,
/// The target arch triple to clean, or None for the host arch
@@ -24,40 +23,75 @@ pub struct CleanOptions<'a> {
pub requested_profile: InternedString,
/// Whether to just clean the doc directory
pub doc: bool,
+ /// If set, doesn't delete anything.
+ pub dry_run: bool,
+}
+
+pub struct CleanContext<'cfg> {
+ pub config: &'cfg Config,
+ progress: Box<dyn CleaningProgressBar + 'cfg>,
+ pub dry_run: bool,
+ num_files_removed: u64,
+ num_dirs_removed: u64,
+ total_bytes_removed: u64,
}
-/// Cleans the package's build artifacts.
+/// Cleans various caches.
pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
let mut target_dir = ws.target_dir();
- let config = ws.config();
+ let config = opts.config;
+ let mut ctx = CleanContext::new(config);
+ ctx.dry_run = opts.dry_run;
- // If the doc option is set, we just want to delete the doc directory.
if opts.doc {
+ if !opts.spec.is_empty() {
+ // FIXME: https://github.com/rust-lang/cargo/issues/8790
+ // This should support the ability to clean specific packages
+ // within the doc directory. It's a little tricky since it
+ // needs to find all documentable targets, but also consider
+ // the fact that target names might overlap with dependency
+ // names and such.
+ bail!("--doc cannot be used with -p");
+ }
+ // If the doc option is set, we just want to delete the doc directory.
target_dir = target_dir.join("doc");
- return clean_entire_folder(&target_dir.into_path_unlocked(), config);
- }
-
- let profiles = Profiles::new(ws, opts.requested_profile)?;
+ ctx.remove_paths(&[target_dir.into_path_unlocked()])?;
+ } else {
+ let profiles = Profiles::new(&ws, opts.requested_profile)?;
+
+ if opts.profile_specified {
+ // After parsing profiles we know the dir-name of the profile, if a profile
+ // was passed from the command line. If so, delete only the directory of
+ // that profile.
+ let dir_name = profiles.get_dir_name();
+ target_dir = target_dir.join(dir_name);
+ }
- if opts.profile_specified {
- // After parsing profiles we know the dir-name of the profile, if a profile
- // was passed from the command line. If so, delete only the directory of
- // that profile.
- let dir_name = profiles.get_dir_name();
- target_dir = target_dir.join(dir_name);
+ // If we have a spec, then we need to delete some packages, otherwise, just
+ // remove the whole target directory and be done with it!
+ //
+ // Note that we don't bother grabbing a lock here as we're just going to
+ // blow it all away anyway.
+ if opts.spec.is_empty() {
+ ctx.remove_paths(&[target_dir.into_path_unlocked()])?;
+ } else {
+ clean_specs(&mut ctx, &ws, &profiles, &opts.targets, &opts.spec)?;
+ }
}
- // If we have a spec, then we need to delete some packages, otherwise, just
- // remove the whole target directory and be done with it!
- //
- // Note that we don't bother grabbing a lock here as we're just going to
- // blow it all away anyway.
- if opts.spec.is_empty() {
- return clean_entire_folder(&target_dir.into_path_unlocked(), config);
- }
+ ctx.display_summary()?;
+ Ok(())
+}
+fn clean_specs(
+ ctx: &mut CleanContext<'_>,
+ ws: &Workspace<'_>,
+ profiles: &Profiles,
+ targets: &[String],
+ spec: &[String],
+) -> CargoResult<()> {
// Clean specific packages.
- let requested_kinds = CompileKind::from_requested_targets(config, &opts.targets)?;
+ let requested_kinds = CompileKind::from_requested_targets(ctx.config, targets)?;
let target_data = RustcTargetData::new(ws, &requested_kinds)?;
let (pkg_set, resolve) = ops::resolve_ws(ws)?;
let prof_dir_name = profiles.get_dir_name();
@@ -75,7 +109,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
.collect::<CargoResult<_>>()?;
// A Vec of layouts. This is a little convoluted because there can only be
// one host_layout.
- let layouts = if opts.targets.is_empty() {
+ let layouts = if targets.is_empty() {
vec![(CompileKind::Host, &host_layout)]
} else {
target_layouts
@@ -96,11 +130,11 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
// Get Packages for the specified specs.
let mut pkg_ids = Vec::new();
- for spec_str in opts.spec.iter() {
+ for spec_str in spec.iter() {
// Translate the spec to a Package.
let spec = PackageIdSpec::parse(spec_str)?;
- if spec.version().is_some() {
- config.shell().warn(&format!(
+ if spec.partial_version().is_some() {
+ ctx.config.shell().warn(&format!(
"version qualifier in `-p {}` is ignored, \
cleaning all versions of `{}` found",
spec_str,
@@ -108,7 +142,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
))?;
}
if spec.url().is_some() {
- config.shell().warn(&format!(
+ ctx.config.shell().warn(&format!(
"url qualifier in `-p {}` ignored, \
cleaning all versions of `{}` found",
spec_str,
@@ -133,20 +167,16 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
}
let packages = pkg_set.get_many(pkg_ids)?;
- let mut progress = CleaningPackagesBar::new(config, packages.len());
+ ctx.progress = Box::new(CleaningPackagesBar::new(ctx.config, packages.len()));
+
for pkg in packages {
let pkg_dir = format!("{}-*", pkg.name());
- progress.on_cleaning_package(&pkg.name())?;
+ ctx.progress.on_cleaning_package(&pkg.name())?;
// Clean fingerprints.
for (_, layout) in &layouts_with_host {
let dir = escape_glob_path(layout.fingerprint())?;
- rm_rf_package_glob_containing_hash(
- &pkg.name(),
- &Path::new(&dir).join(&pkg_dir),
- config,
- &mut progress,
- )?;
+ ctx.rm_rf_package_glob_containing_hash(&pkg.name(), &Path::new(&dir).join(&pkg_dir))?;
}
for target in pkg.targets() {
@@ -154,11 +184,9 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
// Get both the build_script_build and the output directory.
for (_, layout) in &layouts_with_host {
let dir = escape_glob_path(layout.build())?;
- rm_rf_package_glob_containing_hash(
+ ctx.rm_rf_package_glob_containing_hash(
&pkg.name(),
&Path::new(&dir).join(&pkg_dir),
- config,
- &mut progress,
)?;
}
continue;
@@ -190,35 +218,35 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
let dir_glob = escape_glob_path(dir)?;
let dir_glob = Path::new(&dir_glob);
- rm_rf_glob(&dir_glob.join(&hashed_name), config, &mut progress)?;
- rm_rf(&dir.join(&unhashed_name), config, &mut progress)?;
+ ctx.rm_rf_glob(&dir_glob.join(&hashed_name))?;
+ ctx.rm_rf(&dir.join(&unhashed_name))?;
// Remove dep-info file generated by rustc. It is not tracked in
// file_types. It does not have a prefix.
let hashed_dep_info = dir_glob.join(format!("{}-*.d", crate_name));
- rm_rf_glob(&hashed_dep_info, config, &mut progress)?;
+ ctx.rm_rf_glob(&hashed_dep_info)?;
let unhashed_dep_info = dir.join(format!("{}.d", crate_name));
- rm_rf(&unhashed_dep_info, config, &mut progress)?;
+ ctx.rm_rf(&unhashed_dep_info)?;
// Remove split-debuginfo files generated by rustc.
let split_debuginfo_obj = dir_glob.join(format!("{}.*.o", crate_name));
- rm_rf_glob(&split_debuginfo_obj, config, &mut progress)?;
+ ctx.rm_rf_glob(&split_debuginfo_obj)?;
let split_debuginfo_dwo = dir_glob.join(format!("{}.*.dwo", crate_name));
- rm_rf_glob(&split_debuginfo_dwo, config, &mut progress)?;
+ ctx.rm_rf_glob(&split_debuginfo_dwo)?;
let split_debuginfo_dwp = dir_glob.join(format!("{}.*.dwp", crate_name));
- rm_rf_glob(&split_debuginfo_dwp, config, &mut progress)?;
+ ctx.rm_rf_glob(&split_debuginfo_dwp)?;
// Remove the uplifted copy.
if let Some(uplift_dir) = uplift_dir {
let uplifted_path = uplift_dir.join(file_type.uplift_filename(target));
- rm_rf(&uplifted_path, config, &mut progress)?;
+ ctx.rm_rf(&uplifted_path)?;
// Dep-info generated by Cargo itself.
let dep_info = uplifted_path.with_extension("d");
- rm_rf(&dep_info, config, &mut progress)?;
+ ctx.rm_rf(&dep_info)?;
}
}
// TODO: what to do about build_script_build?
let dir = escape_glob_path(layout.incremental())?;
let incremental = Path::new(&dir).join(format!("{}-*", crate_name));
- rm_rf_glob(&incremental, config, &mut progress)?;
+ ctx.rm_rf_glob(&incremental)?;
}
}
}
@@ -234,92 +262,193 @@ fn escape_glob_path(pattern: &Path) -> CargoResult<String> {
Ok(glob::Pattern::escape(pattern))
}
-/// Glob remove artifacts for the provided `package`
-///
-/// Make sure the artifact is for `package` and not another crate that is prefixed by
-/// `package` by getting the original name stripped of the trailing hash and possible
-/// extension
-fn rm_rf_package_glob_containing_hash(
- package: &str,
- pattern: &Path,
- config: &Config,
- progress: &mut dyn CleaningProgressBar,
-) -> CargoResult<()> {
- // TODO: Display utf8 warning to user? Or switch to globset?
- let pattern = pattern
- .to_str()
- .ok_or_else(|| anyhow::anyhow!("expected utf-8 path"))?;
- for path in glob::glob(pattern)? {
- let path = path?;
-
- let pkg_name = path
- .file_name()
- .and_then(std::ffi::OsStr::to_str)
- .and_then(|artifact| artifact.rsplit_once('-'))
- .ok_or_else(|| anyhow::anyhow!("expected utf-8 path"))?
- .0;
-
- if pkg_name != package {
- continue;
+impl<'cfg> CleanContext<'cfg> {
+ pub fn new(config: &'cfg Config) -> Self {
+ // This progress bar will get replaced, this is just here to avoid needing
+ // an Option until the actual bar is created.
+ let progress = CleaningFolderBar::new(config, 0);
+ CleanContext {
+ config,
+ progress: Box::new(progress),
+ dry_run: false,
+ num_files_removed: 0,
+ num_dirs_removed: 0,
+ total_bytes_removed: 0,
}
+ }
- rm_rf(&path, config, progress)?;
+ /// Glob remove artifacts for the provided `package`
+ ///
+ /// Make sure the artifact is for `package` and not another crate that is prefixed by
+ /// `package` by getting the original name stripped of the trailing hash and possible
+ /// extension
+ fn rm_rf_package_glob_containing_hash(
+ &mut self,
+ package: &str,
+ pattern: &Path,
+ ) -> CargoResult<()> {
+ // TODO: Display utf8 warning to user? Or switch to globset?
+ let pattern = pattern
+ .to_str()
+ .ok_or_else(|| anyhow::anyhow!("expected utf-8 path"))?;
+ for path in glob::glob(pattern)? {
+ let path = path?;
+
+ let pkg_name = path
+ .file_name()
+ .and_then(std::ffi::OsStr::to_str)
+ .and_then(|artifact| artifact.rsplit_once('-'))
+ .ok_or_else(|| anyhow::anyhow!("expected utf-8 path"))?
+ .0;
+
+ if pkg_name != package {
+ continue;
+ }
+
+ self.rm_rf(&path)?;
+ }
+ Ok(())
}
- Ok(())
-}
-fn rm_rf_glob(
- pattern: &Path,
- config: &Config,
- progress: &mut dyn CleaningProgressBar,
-) -> CargoResult<()> {
- // TODO: Display utf8 warning to user? Or switch to globset?
- let pattern = pattern
- .to_str()
- .ok_or_else(|| anyhow::anyhow!("expected utf-8 path"))?;
- for path in glob::glob(pattern)? {
- rm_rf(&path?, config, progress)?;
+ fn rm_rf_glob(&mut self, pattern: &Path) -> CargoResult<()> {
+ // TODO: Display utf8 warning to user? Or switch to globset?
+ let pattern = pattern
+ .to_str()
+ .ok_or_else(|| anyhow::anyhow!("expected utf-8 path"))?;
+ for path in glob::glob(pattern)? {
+ self.rm_rf(&path?)?;
+ }
+ Ok(())
}
- Ok(())
-}
-fn rm_rf(path: &Path, config: &Config, progress: &mut dyn CleaningProgressBar) -> CargoResult<()> {
- if fs::symlink_metadata(path).is_err() {
- return Ok(());
+ pub fn rm_rf(&mut self, path: &Path) -> CargoResult<()> {
+ let meta = match fs::symlink_metadata(path) {
+ Ok(meta) => meta,
+ Err(e) => {
+ if e.kind() != std::io::ErrorKind::NotFound {
+ self.config
+ .shell()
+ .warn(&format!("cannot access {}: {e}", path.display()))?;
+ }
+ return Ok(());
+ }
+ };
+
+ // dry-run displays paths while walking, so don't print here.
+ if !self.dry_run {
+ self.config
+ .shell()
+ .verbose(|shell| shell.status("Removing", path.display()))?;
+ }
+ self.progress.display_now()?;
+
+ let mut rm_file = |path: &Path, meta: Result<std::fs::Metadata, _>| {
+ if let Ok(meta) = meta {
+ // Note: This can over-count bytes removed for hard-linked
+ // files. It also under-counts since it only counts the exact
+ // byte sizes and not the block sizes.
+ self.total_bytes_removed += meta.len();
+ }
+ self.num_files_removed += 1;
+ if !self.dry_run {
+ paths::remove_file(path)?;
+ }
+ Ok(())
+ };
+
+ if !meta.is_dir() {
+ return rm_file(path, Ok(meta));
+ }
+
+ for entry in walkdir::WalkDir::new(path).contents_first(true) {
+ let entry = entry?;
+ self.progress.on_clean()?;
+ if self.dry_run {
+ // This prints the path without the "Removing" status since I feel
+ // like it can be surprising or even frightening if cargo says it
+ // is removing something without actually removing it. And I can't
+ // come up with a different verb to use as the status.
+ self.config
+ .shell()
+ .verbose(|shell| Ok(writeln!(shell.out(), "{}", entry.path().display())?))?;
+ }
+ if entry.file_type().is_dir() {
+ self.num_dirs_removed += 1;
+ // The contents should have been removed by now, but sometimes a race condition is hit
+ // where other files have been added by the OS. `paths::remove_dir_all` also falls back
+ // to `std::fs::remove_dir_all`, which may be more reliable than a simple walk in
+ // platform-specific edge cases.
+ if !self.dry_run {
+ paths::remove_dir_all(entry.path())?;
+ }
+ } else {
+ rm_file(entry.path(), entry.metadata())?;
+ }
+ }
+
+ Ok(())
}
- config
- .shell()
- .verbose(|shell| shell.status("Removing", path.display()))?;
- progress.display_now()?;
-
- for entry in walkdir::WalkDir::new(path).contents_first(true) {
- let entry = entry?;
- progress.on_clean()?;
- if entry.file_type().is_dir() {
- // The contents should have been removed by now, but sometimes a race condition is hit
- // where other files have been added by the OS. `paths::remove_dir_all` also falls back
- // to `std::fs::remove_dir_all`, which may be more reliable than a simple walk in
- // platform-specific edge cases.
- paths::remove_dir_all(entry.path())
- .with_context(|| "could not remove build directory")?;
+ fn display_summary(&self) -> CargoResult<()> {
+ let status = if self.dry_run { "Summary" } else { "Removed" };
+ let byte_count = if self.total_bytes_removed == 0 {
+ String::new()
} else {
- paths::remove_file(entry.path()).with_context(|| "failed to remove build artifact")?;
+ // Don't show a fractional number of bytes.
+ if self.total_bytes_removed < 1024 {
+ format!(", {}B total", self.total_bytes_removed)
+ } else {
+ let (bytes, unit) = human_readable_bytes(self.total_bytes_removed);
+ format!(", {bytes:.1}{unit} total")
+ }
+ };
+ // I think displaying the number of directories removed isn't
+ // particularly interesting to the user. However, if there are 0
+ // files, and a nonzero number of directories, cargo should indicate
+ // that it did *something*, so directory counts are only shown in that
+ // case.
+ let file_count = match (self.num_files_removed, self.num_dirs_removed) {
+ (0, 0) => format!("0 files"),
+ (0, 1) => format!("1 directory"),
+ (0, 2..) => format!("{} directories", self.num_dirs_removed),
+ (1, _) => format!("1 file"),
+ (2.., _) => format!("{} files", self.num_files_removed),
+ };
+ self.config
+ .shell()
+ .status(status, format!("{file_count}{byte_count}"))?;
+ if self.dry_run {
+ self.config
+ .shell()
+ .warn("no files deleted due to --dry-run")?;
}
+ Ok(())
}
- Ok(())
-}
-
-fn clean_entire_folder(path: &Path, config: &Config) -> CargoResult<()> {
- let num_paths = walkdir::WalkDir::new(path).into_iter().count();
- let mut progress = CleaningFolderBar::new(config, num_paths);
- rm_rf(path, config, &mut progress)
+ /// Deletes all of the given paths, showing a progress bar as it proceeds.
+ ///
+ /// If any path does not exist, or is not accessible, this will not
+ /// generate an error. This only generates an error for other issues, like
+ /// not being able to write to the console.
+ pub fn remove_paths(&mut self, paths: &[PathBuf]) -> CargoResult<()> {
+ let num_paths = paths
+ .iter()
+ .map(|path| walkdir::WalkDir::new(path).into_iter().count())
+ .sum();
+ self.progress = Box::new(CleaningFolderBar::new(self.config, num_paths));
+ for path in paths {
+ self.rm_rf(path)?;
+ }
+ Ok(())
+ }
}
trait CleaningProgressBar {
fn display_now(&mut self) -> CargoResult<()>;
fn on_clean(&mut self) -> CargoResult<()>;
+ fn on_cleaning_package(&mut self, _package: &str) -> CargoResult<()> {
+ Ok(())
+ }
}
struct CleaningFolderBar<'cfg> {
@@ -372,13 +501,6 @@ impl<'cfg> CleaningPackagesBar<'cfg> {
}
}
- fn on_cleaning_package(&mut self, package: &str) -> CargoResult<()> {
- self.cur += 1;
- self.package_being_cleaned = String::from(package);
- self.bar
- .tick(self.cur_progress(), self.max, &self.format_message())
- }
-
fn cur_progress(&self) -> usize {
std::cmp::min(self.cur, self.max)
}
@@ -403,4 +525,11 @@ impl<'cfg> CleaningProgressBar for CleaningPackagesBar<'cfg> {
self.num_files_folders_cleaned += 1;
Ok(())
}
+
+ fn on_cleaning_package(&mut self, package: &str) -> CargoResult<()> {
+ self.cur += 1;
+ self.package_being_cleaned = String::from(package);
+ self.bar
+ .tick(self.cur_progress(), self.max, &self.format_message())
+ }
}
diff --git a/src/tools/cargo/src/cargo/ops/cargo_compile/mod.rs b/src/tools/cargo/src/cargo/ops/cargo_compile/mod.rs
index 1247ceda7..9cf8599c4 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_compile/mod.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_compile/mod.rs
@@ -184,7 +184,7 @@ pub fn print<'a>(
process.args(args);
}
if let CompileKind::Target(t) = kind {
- process.arg("--target").arg(t.short_name());
+ process.arg("--target").arg(t.rustc_target());
}
process.arg("--print").arg(print_opt_value);
process.exec()?;
@@ -237,7 +237,7 @@ pub fn create_bcx<'a, 'cfg>(
}
config.validate_term_config()?;
- let target_data = RustcTargetData::new(ws, &build_config.requested_kinds)?;
+ let mut target_data = RustcTargetData::new(ws, &build_config.requested_kinds)?;
let specs = spec.to_package_id_specs(ws)?;
let has_dev_units = {
@@ -261,14 +261,16 @@ pub fn create_bcx<'a, 'cfg>(
HasDevUnits::No
}
};
+ let max_rust_version = ws.rust_version();
let resolve = ops::resolve_ws_with_opts(
ws,
- &target_data,
+ &mut target_data,
&build_config.requested_kinds,
cli_features,
&specs,
has_dev_units,
crate::core::resolver::features::ForceAllTargets::No,
+ max_rust_version,
)?;
let WorkspaceResolve {
mut pkg_set,
@@ -279,7 +281,7 @@ pub fn create_bcx<'a, 'cfg>(
let std_resolve_features = if let Some(crates) = &config.cli_unstable().build_std {
let (std_package_set, std_resolve, std_features) =
- standard_lib::resolve_std(ws, &target_data, &build_config, crates)?;
+ standard_lib::resolve_std(ws, &mut target_data, &build_config, crates)?;
pkg_set.add_set(std_package_set);
Some((std_resolve, std_features))
} else {
@@ -316,8 +318,8 @@ pub fn create_bcx<'a, 'cfg>(
}
let (extra_args, extra_args_name) = match (target_rustc_args, target_rustdoc_args) {
- (&Some(ref args), _) => (Some(args.clone()), "rustc"),
- (_, &Some(ref args)) => (Some(args.clone()), "rustdoc"),
+ (Some(args), _) => (Some(args.clone()), "rustc"),
+ (_, Some(args)) => (Some(args.clone()), "rustdoc"),
_ => (None, ""),
};
@@ -487,12 +489,11 @@ pub fn create_bcx<'a, 'cfg>(
);
for unit in unit_graph.keys() {
- let version = match unit.pkg.rust_version() {
- Some(v) => v,
- None => continue,
+ let Some(version) = unit.pkg.rust_version() else {
+ continue;
};
- let req = semver::VersionReq::parse(version).unwrap();
+ let req = version.caret_req();
if req.matches(&untagged_version) {
continue;
}
@@ -506,7 +507,7 @@ pub fn create_bcx<'a, 'cfg>(
} else if !unit.is_local() {
format!(
"Either upgrade to rustc {} or newer, or use\n\
- cargo update -p {}@{} --precise ver\n\
+ cargo update {}@{} --precise ver\n\
where `ver` is the latest version of `{}` supporting rustc {}",
version,
unit.pkg.name(),
diff --git a/src/tools/cargo/src/cargo/ops/cargo_fetch.rs b/src/tools/cargo/src/cargo/ops/cargo_fetch.rs
index 273bce284..6acdbddef 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_fetch.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_fetch.rs
@@ -31,7 +31,7 @@ pub fn fetch<'a>(
&options.targets,
CompileMode::Build,
)?;
- let data = RustcTargetData::new(ws, &build_config.requested_kinds)?;
+ let mut data = RustcTargetData::new(ws, &build_config.requested_kinds)?;
let mut fetched_packages = HashSet::new();
let mut deps_to_fetch = ws.members().map(|p| p.package_id()).collect::<Vec<_>>();
let mut to_download = Vec::new();
@@ -70,7 +70,8 @@ pub fn fetch<'a>(
// If -Zbuild-std was passed, download dependencies for the standard library.
// We don't know ahead of time what jobs we'll be running, so tell `std_crates` that.
if let Some(crates) = standard_lib::std_crates(config, None) {
- let (std_package_set, _, _) = standard_lib::resolve_std(ws, &data, &build_config, &crates)?;
+ let (std_package_set, _, _) =
+ standard_lib::resolve_std(ws, &mut data, &build_config, &crates)?;
packages.add_set(std_package_set);
}
diff --git a/src/tools/cargo/src/cargo/ops/cargo_generate_lockfile.rs b/src/tools/cargo/src/cargo/ops/cargo_generate_lockfile.rs
index fddf83f19..a83a92ccc 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_generate_lockfile.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_generate_lockfile.rs
@@ -4,23 +4,24 @@ use crate::core::{PackageId, PackageIdSpec};
use crate::core::{Resolve, SourceId, Workspace};
use crate::ops;
use crate::util::config::Config;
+use crate::util::style;
use crate::util::CargoResult;
-use anyhow::Context;
+use anstyle::Style;
use std::collections::{BTreeMap, HashSet};
-use termcolor::Color::{self, Cyan, Green, Red, Yellow};
use tracing::debug;
pub struct UpdateOptions<'a> {
pub config: &'a Config,
pub to_update: Vec<String>,
pub precise: Option<&'a str>,
- pub aggressive: bool,
+ pub recursive: bool,
pub dry_run: bool,
pub workspace: bool,
}
pub fn generate_lockfile(ws: &Workspace<'_>) -> CargoResult<()> {
let mut registry = PackageRegistry::new(ws.config())?;
+ let max_rust_version = ws.rust_version();
let mut resolve = ops::resolve_with_previous(
&mut registry,
ws,
@@ -30,14 +31,15 @@ pub fn generate_lockfile(ws: &Workspace<'_>) -> CargoResult<()> {
None,
&[],
true,
+ max_rust_version,
)?;
ops::write_pkg_lockfile(ws, &mut resolve)?;
Ok(())
}
pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoResult<()> {
- if opts.aggressive && opts.precise.is_some() {
- anyhow::bail!("cannot specify both aggressive and precise simultaneously")
+ if opts.recursive && opts.precise.is_some() {
+ anyhow::bail!("cannot specify both recursive and precise simultaneously")
}
if ws.members().count() == 0 {
@@ -48,6 +50,8 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
// that we're synchronized against other Cargos.
let _lock = ws.config().acquire_package_cache_lock()?;
+ let max_rust_version = ws.rust_version();
+
let previous_resolve = match ops::load_pkg_lockfile(ws)? {
Some(resolve) => resolve,
None => {
@@ -67,6 +71,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
None,
&[],
true,
+ max_rust_version,
)?
}
}
@@ -83,27 +88,27 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
} else {
let mut sources = Vec::new();
for name in opts.to_update.iter() {
- let dep = previous_resolve.query(name)?;
- if opts.aggressive {
- fill_with_deps(&previous_resolve, dep, &mut to_avoid, &mut HashSet::new());
+ let pid = previous_resolve.query(name)?;
+ if opts.recursive {
+ fill_with_deps(&previous_resolve, pid, &mut to_avoid, &mut HashSet::new());
} else {
- to_avoid.insert(dep);
+ to_avoid.insert(pid);
sources.push(match opts.precise {
Some(precise) => {
// TODO: see comment in `resolve.rs` as well, but this
// seems like a pretty hokey reason to single out
// the registry as well.
- let precise = if dep.source_id().is_registry() {
- semver::Version::parse(precise).with_context(|| {
- format!("invalid version format for precise version `{}`", precise)
- })?;
- format!("{}={}->{}", dep.name(), dep.version(), precise)
+ if pid.source_id().is_registry() {
+ pid.source_id().with_precise_registry_version(
+ pid.name(),
+ pid.version(),
+ precise,
+ )?
} else {
- precise.to_string()
- };
- dep.source_id().with_precise(Some(precise))
+ pid.source_id().with_precise(Some(precise.to_string()))
+ }
}
- None => dep.source_id().with_precise(None),
+ None => pid.source_id().with_precise(None),
});
}
if let Ok(unused_id) =
@@ -125,10 +130,11 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
Some(&to_avoid),
&[],
true,
+ max_rust_version,
)?;
// Summarize what is changing for the user.
- let print_change = |status: &str, msg: String, color: Color| {
+ let print_change = |status: &str, msg: String, color: &Style| {
opts.config.shell().status_with_color(status, msg, color)
};
for (removed, added) in compare_dependency_graphs(&previous_resolve, &resolve) {
@@ -144,16 +150,16 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
};
if removed[0].version() > added[0].version() {
- print_change("Downgrading", msg, Yellow)?;
+ print_change("Downgrading", msg, &style::WARN)?;
} else {
- print_change("Updating", msg, Green)?;
+ print_change("Updating", msg, &style::GOOD)?;
}
} else {
for package in removed.iter() {
- print_change("Removing", format!("{}", package), Red)?;
+ print_change("Removing", format!("{}", package), &style::ERROR)?;
}
for package in added.iter() {
- print_change("Adding", format!("{}", package), Cyan)?;
+ print_change("Adding", format!("{}", package), &style::NOTE)?;
}
}
}
@@ -198,9 +204,8 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
.filter(|a| {
// If this package ID is not found in `b`, then it's definitely
// in the subtracted set.
- let i = match b.binary_search(a) {
- Ok(i) => i,
- Err(..) => return true,
+ let Ok(i) = b.binary_search(a) else {
+ return true;
};
// If we've found `a` in `b`, then we iterate over all instances
diff --git a/src/tools/cargo/src/cargo/ops/cargo_install.rs b/src/tools/cargo/src/cargo/ops/cargo_install.rs
index 8ddfa4fab..957ab43e6 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_install.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_install.rs
@@ -5,16 +5,17 @@ use std::{env, fs};
use crate::core::compiler::{CompileKind, DefaultExecutor, Executor, UnitOutput};
use crate::core::{
- Dependency, Edition, Package, PackageId, PackageIdSpec, Source, SourceId, Target, Workspace,
+ Dependency, Edition, Package, PackageId, PackageIdSpec, SourceId, Target, Workspace,
};
use crate::ops::{common_for_install_and_uninstall::*, FilterRule};
use crate::ops::{CompileFilter, Packages};
+use crate::sources::source::Source;
use crate::sources::{GitSource, PathSource, SourceConfigMap};
use crate::util::errors::CargoResult;
-use crate::util::{Config, Filesystem, Rustc, ToSemver, VersionReqExt};
+use crate::util::{Config, Filesystem, Rustc};
use crate::{drop_println, ops};
-use anyhow::{bail, format_err, Context as _};
+use anyhow::{bail, Context as _};
use cargo_util::paths;
use itertools::Itertools;
use semver::VersionReq;
@@ -38,12 +39,12 @@ impl Drop for Transaction {
}
}
-struct InstallablePackage<'cfg, 'a> {
+struct InstallablePackage<'cfg> {
config: &'cfg Config,
opts: ops::CompileOptions,
root: Filesystem,
source_id: SourceId,
- vers: Option<&'a str>,
+ vers: Option<VersionReq>,
force: bool,
no_track: bool,
@@ -53,7 +54,7 @@ struct InstallablePackage<'cfg, 'a> {
target: String,
}
-impl<'cfg, 'a> InstallablePackage<'cfg, 'a> {
+impl<'cfg> InstallablePackage<'cfg> {
// Returns pkg to install. None if pkg is already installed
pub fn new(
config: &'cfg Config,
@@ -62,12 +63,12 @@ impl<'cfg, 'a> InstallablePackage<'cfg, 'a> {
krate: Option<&str>,
source_id: SourceId,
from_cwd: bool,
- vers: Option<&'a str>,
- original_opts: &'a ops::CompileOptions,
+ vers: Option<&VersionReq>,
+ original_opts: &ops::CompileOptions,
force: bool,
no_track: bool,
needs_update_if_source_is_index: bool,
- ) -> CargoResult<Option<InstallablePackage<'cfg, 'a>>> {
+ ) -> CargoResult<Option<Self>> {
if let Some(name) = krate {
if name == "." {
bail!(
@@ -82,8 +83,8 @@ impl<'cfg, 'a> InstallablePackage<'cfg, 'a> {
let pkg = {
let dep = {
if let Some(krate) = krate {
- let vers = if let Some(vers_flag) = vers {
- Some(parse_semver_flag(vers_flag)?.to_string())
+ let vers = if let Some(vers) = vers {
+ Some(vers.to_string())
} else if source_id.is_registry() {
// Avoid pre-release versions from crate.io
// unless explicitly asked for
@@ -234,7 +235,7 @@ impl<'cfg, 'a> InstallablePackage<'cfg, 'a> {
opts,
root,
source_id,
- vers,
+ vers: vers.cloned(),
force,
no_track,
@@ -604,7 +605,7 @@ Consider enabling some of the needed features by passing, e.g., `--features=\"{e
pub fn install(
config: &Config,
root: Option<&str>,
- krates: Vec<(&str, Option<&str>)>,
+ krates: Vec<(String, Option<VersionReq>)>,
source_id: SourceId,
from_cwd: bool,
opts: &ops::CompileOptions,
@@ -617,9 +618,9 @@ pub fn install(
let (installed_anything, scheduled_error) = if krates.len() <= 1 {
let (krate, vers) = krates
- .into_iter()
+ .iter()
.next()
- .map(|(k, v)| (Some(k), v))
+ .map(|(k, v)| (Some(k.as_str()), v.as_ref()))
.unwrap_or((None, None));
let installable_pkg = InstallablePackage::new(
config, root, map, krate, source_id, from_cwd, vers, opts, force, no_track, true,
@@ -637,7 +638,7 @@ pub fn install(
let mut did_update = false;
let pkgs_to_install: Vec<_> = krates
- .into_iter()
+ .iter()
.filter_map(|(krate, vers)| {
let root = root.clone();
let map = map.clone();
@@ -645,10 +646,10 @@ pub fn install(
config,
root,
map,
- Some(krate),
+ Some(krate.as_str()),
source_id,
from_cwd,
- vers,
+ vers.as_ref(),
opts,
force,
no_track,
@@ -660,12 +661,12 @@ pub fn install(
}
Ok(None) => {
// Already installed
- succeeded.push(krate);
+ succeeded.push(krate.as_str());
None
}
Err(e) => {
crate::display_error(&e, &mut config.shell());
- failed.push(krate);
+ failed.push(krate.as_str());
// We assume an update was performed if we got an error.
did_update = true;
None
@@ -805,54 +806,6 @@ fn make_ws_rustc_target<'cfg>(
Ok((ws, rustc, target))
}
-/// Parses x.y.z as if it were =x.y.z, and gives CLI-specific error messages in the case of invalid
-/// values.
-fn parse_semver_flag(v: &str) -> CargoResult<VersionReq> {
- // If the version begins with character <, >, =, ^, ~ parse it as a
- // version range, otherwise parse it as a specific version
- let first = v
- .chars()
- .next()
- .ok_or_else(|| format_err!("no version provided for the `--version` flag"))?;
-
- let is_req = "<>=^~".contains(first) || v.contains('*');
- if is_req {
- match v.parse::<VersionReq>() {
- Ok(v) => Ok(v),
- Err(_) => bail!(
- "the `--version` provided, `{}`, is \
- not a valid semver version requirement\n\n\
- Please have a look at \
- https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html \
- for the correct format",
- v
- ),
- }
- } else {
- match v.to_semver() {
- Ok(v) => Ok(VersionReq::exact(&v)),
- Err(e) => {
- let mut msg = format!(
- "the `--version` provided, `{}`, is \
- not a valid semver version: {}\n",
- v, e
- );
-
- // If it is not a valid version but it is a valid version
- // requirement, add a note to the warning
- if v.parse::<VersionReq>().is_ok() {
- msg.push_str(&format!(
- "\nif you want to specify semver range, \
- add an explicit qualifier, like ^{}",
- v
- ));
- }
- bail!(msg);
- }
- }
- }
-}
-
/// Display a list of installed binaries.
pub fn install_list(dst: Option<&str>, config: &Config) -> CargoResult<()> {
let root = resolve_root(dst, config)?;
diff --git a/src/tools/cargo/src/cargo/ops/cargo_new.rs b/src/tools/cargo/src/cargo/ops/cargo_new.rs
index 0809cefc3..78b3cc4f6 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_new.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_new.rs
@@ -93,7 +93,6 @@ struct MkOptions<'a> {
path: &'a Path,
name: &'a str,
source_files: Vec<SourceFileInformation>,
- bin: bool,
edition: Option<&'a str>,
registry: Option<&'a str>,
}
@@ -448,7 +447,6 @@ pub fn new(opts: &NewOptions, config: &Config) -> CargoResult<()> {
path,
name,
source_files: vec![plan_new_source_file(opts.kind.is_bin(), name.to_string())],
- bin: is_bin,
edition: opts.edition.as_deref(),
registry: opts.registry.as_deref(),
};
@@ -553,7 +551,6 @@ pub fn init(opts: &NewOptions, config: &Config) -> CargoResult<NewProjectKind> {
version_control,
path,
name,
- bin: has_bin,
source_files: src_paths_types,
edition: opts.edition.as_deref(),
registry: opts.registry.as_deref(),
@@ -745,9 +742,6 @@ fn mk(config: &Config, opts: &MkOptions<'_>) -> CargoResult<()> {
// for all mutually-incompatible VCS in terms of syntax are in sync.
let mut ignore = IgnoreList::new();
ignore.push("/target", "^target$", "target");
- if !opts.bin {
- ignore.push("/Cargo.lock", "^Cargo.lock$", "Cargo.lock");
- }
let vcs = opts.version_control.unwrap_or_else(|| {
let in_existing_vcs = existing_vcs_repo(path.parent().unwrap_or(path), config.cwd());
@@ -823,11 +817,10 @@ fn mk(config: &Config, opts: &MkOptions<'_>) -> CargoResult<()> {
}
// Try to inherit the workspace lints key if it exists.
- if config.cli_unstable().lints
- && workspace_document
- .get("workspace")
- .and_then(|workspace| workspace.get("lints"))
- .is_some()
+ if workspace_document
+ .get("workspace")
+ .and_then(|workspace| workspace.get("lints"))
+ .is_some()
{
let mut table = toml_edit::Table::new();
table["workspace"] = toml_edit::value(true);
diff --git a/src/tools/cargo/src/cargo/ops/cargo_output_metadata.rs b/src/tools/cargo/src/cargo/ops/cargo_output_metadata.rs
index c0a63aa75..83dae50ea 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_output_metadata.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_output_metadata.rs
@@ -126,7 +126,7 @@ fn build_resolve_graph(
// How should this work?
let requested_kinds =
CompileKind::from_requested_targets(ws.config(), &metadata_opts.filter_platforms)?;
- let target_data = RustcTargetData::new(ws, &requested_kinds)?;
+ let mut target_data = RustcTargetData::new(ws, &requested_kinds)?;
// Resolve entire workspace.
let specs = Packages::All.to_package_id_specs(ws)?;
let force_all = if metadata_opts.filter_platforms.is_empty() {
@@ -135,16 +135,19 @@ fn build_resolve_graph(
crate::core::resolver::features::ForceAllTargets::No
};
+ let max_rust_version = ws.rust_version();
+
// Note that even with --filter-platform we end up downloading host dependencies as well,
// as that is the behavior of download_accessible.
let ws_resolve = ops::resolve_ws_with_opts(
ws,
- &target_data,
+ &mut target_data,
&requested_kinds,
&metadata_opts.cli_features,
&specs,
HasDevUnits::Yes,
force_all,
+ max_rust_version,
)?;
let package_map: BTreeMap<PackageId, Package> = ws_resolve
@@ -313,7 +316,7 @@ fn build_resolve_graph_r(
dep_kinds,
},
// No lib or artifact dep exists.
- // Ususally this mean parent depending on non-lib bin crate.
+ // Usually this mean parent depending on non-lib bin crate.
(None, _) => continue,
};
diff --git a/src/tools/cargo/src/cargo/ops/cargo_package.rs b/src/tools/cargo/src/cargo/ops/cargo_package.rs
index 93469607b..b6423aa96 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_package.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_package.rs
@@ -237,7 +237,7 @@ fn build_ar_list(
let rel_str = rel_path.to_str().ok_or_else(|| {
anyhow::format_err!("non-utf8 path in source directory: {}", rel_path.display())
})?;
- match rel_str.as_ref() {
+ match rel_str {
"Cargo.lock" => continue,
VCS_INFO_FILE | ORIGINAL_MANIFEST_FILE => anyhow::bail!(
"invalid inclusion of reserved file name {} in package source",
@@ -423,6 +423,8 @@ fn build_lock(ws: &Workspace<'_>, orig_pkg: &Package) -> CargoResult<String> {
TomlManifest::to_real_manifest(&toml_manifest, false, source_id, package_root, config)?;
let new_pkg = Package::new(manifest, orig_pkg.manifest_path());
+ let max_rust_version = new_pkg.rust_version().cloned();
+
// Regenerate Cargo.lock using the old one as a guide.
let tmp_ws = Workspace::ephemeral(new_pkg, ws.config(), None, true)?;
let mut tmp_reg = PackageRegistry::new(ws.config())?;
@@ -435,6 +437,7 @@ fn build_lock(ws: &Workspace<'_>, orig_pkg: &Package) -> CargoResult<String> {
None,
&[],
true,
+ max_rust_version.as_ref(),
)?;
let pkg_set = ops::get_resolved_packages(&new_resolve, tmp_reg)?;
@@ -991,17 +994,15 @@ fn report_hash_difference(orig: &HashMap<PathBuf, u64>, after: &HashMap<PathBuf,
// To help out in situations like this, issue about weird filenames when
// packaging as a "heads up" that something may not work on other platforms.
fn check_filename(file: &Path, shell: &mut Shell) -> CargoResult<()> {
- let name = match file.file_name() {
- Some(name) => name,
- None => return Ok(()),
+ let Some(name) = file.file_name() else {
+ return Ok(());
};
- let name = match name.to_str() {
- Some(name) => name,
- None => anyhow::bail!(
+ let Some(name) = name.to_str() else {
+ anyhow::bail!(
"path does not have a unicode filename which may not unpack \
on all platforms: {}",
file.display()
- ),
+ )
};
let bad_chars = ['/', '\\', '<', '>', ':', '"', '|', '?', '*'];
if let Some(c) = bad_chars.iter().find(|c| name.contains(**c)) {
diff --git a/src/tools/cargo/src/cargo/ops/cargo_pkgid.rs b/src/tools/cargo/src/cargo/ops/cargo_pkgid.rs
index eeed6ac02..bbae154a7 100644
--- a/src/tools/cargo/src/cargo/ops/cargo_pkgid.rs
+++ b/src/tools/cargo/src/cargo/ops/cargo_pkgid.rs
@@ -3,9 +3,8 @@ use crate::ops;
use crate::util::CargoResult;
pub fn pkgid(ws: &Workspace<'_>, spec: Option<&str>) -> CargoResult<PackageIdSpec> {
- let resolve = match ops::load_pkg_lockfile(ws)? {
- Some(resolve) => resolve,
- None => anyhow::bail!("a Cargo.lock must exist for this command"),
+ let Some(resolve) = ops::load_pkg_lockfile(ws)? else {
+ anyhow::bail!("a Cargo.lock must exist for this command")
};
let pkgid = match spec {
diff --git a/src/tools/cargo/src/cargo/ops/common_for_install_and_uninstall.rs b/src/tools/cargo/src/cargo/ops/common_for_install_and_uninstall.rs
index f33847d57..0934cbd29 100644
--- a/src/tools/cargo/src/cargo/ops/common_for_install_and_uninstall.rs
+++ b/src/tools/cargo/src/cargo/ops/common_for_install_and_uninstall.rs
@@ -12,8 +12,10 @@ use serde::{Deserialize, Serialize};
use crate::core::compiler::{DirtyReason, Freshness};
use crate::core::Target;
-use crate::core::{Dependency, FeatureValue, Package, PackageId, QueryKind, Source, SourceId};
+use crate::core::{Dependency, FeatureValue, Package, PackageId, SourceId};
use crate::ops::{self, CompileFilter, CompileOptions};
+use crate::sources::source::QueryKind;
+use crate::sources::source::Source;
use crate::sources::PathSource;
use crate::util::errors::CargoResult;
use crate::util::Config;
diff --git a/src/tools/cargo/src/cargo/ops/fix.rs b/src/tools/cargo/src/cargo/ops/fix.rs
index 0e678d61c..9d6459294 100644
--- a/src/tools/cargo/src/cargo/ops/fix.rs
+++ b/src/tools/cargo/src/cargo/ops/fix.rs
@@ -243,22 +243,26 @@ fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<(
// 2018 without `resolver` set must be V1
assert_eq!(ws.resolve_behavior(), ResolveBehavior::V1);
let specs = opts.compile_opts.spec.to_package_id_specs(ws)?;
- let target_data = RustcTargetData::new(ws, &opts.compile_opts.build_config.requested_kinds)?;
- let resolve_differences = |has_dev_units| -> CargoResult<(WorkspaceResolve<'_>, DiffMap)> {
+ let mut target_data =
+ RustcTargetData::new(ws, &opts.compile_opts.build_config.requested_kinds)?;
+ let mut resolve_differences = |has_dev_units| -> CargoResult<(WorkspaceResolve<'_>, DiffMap)> {
+ let max_rust_version = ws.rust_version();
+
let ws_resolve = ops::resolve_ws_with_opts(
ws,
- &target_data,
+ &mut target_data,
&opts.compile_opts.build_config.requested_kinds,
&opts.compile_opts.cli_features,
&specs,
has_dev_units,
crate::core::resolver::features::ForceAllTargets::No,
+ max_rust_version,
)?;
let feature_opts = FeatureOpts::new_behavior(ResolveBehavior::V2, has_dev_units);
let v2_features = FeatureResolver::resolve(
ws,
- &target_data,
+ &mut target_data,
&ws_resolve.targeted_resolve,
&ws_resolve.pkg_set,
&opts.compile_opts.cli_features,
@@ -916,15 +920,12 @@ impl FixArgs {
/// Validates the edition, and sends a message indicating what is being
/// done. Returns a flag indicating whether this fix should be run.
fn can_run_rustfix(&self, config: &Config) -> CargoResult<bool> {
- let to_edition = match self.prepare_for_edition {
- Some(s) => s,
- None => {
- return Message::Fixing {
- file: self.file.display().to_string(),
- }
- .post(config)
- .and(Ok(true));
+ let Some(to_edition) = self.prepare_for_edition else {
+ return Message::Fixing {
+ file: self.file.display().to_string(),
}
+ .post(config)
+ .and(Ok(true));
};
// Unfortunately determining which cargo targets are being built
// isn't easy, and each target can be a different edition. The
diff --git a/src/tools/cargo/src/cargo/ops/lockfile.rs b/src/tools/cargo/src/cargo/ops/lockfile.rs
index b27a7e742..26456e560 100644
--- a/src/tools/cargo/src/cargo/ops/lockfile.rs
+++ b/src/tools/cargo/src/cargo/ops/lockfile.rs
@@ -2,7 +2,6 @@ use std::io::prelude::*;
use crate::core::{resolver, Resolve, ResolveVersion, Workspace};
use crate::util::errors::CargoResult;
-use crate::util::toml as cargo_toml;
use crate::util::Filesystem;
use anyhow::Context as _;
@@ -20,8 +19,7 @@ pub fn load_pkg_lockfile(ws: &Workspace<'_>) -> CargoResult<Option<Resolve>> {
.with_context(|| format!("failed to read file: {}", f.path().display()))?;
let resolve = (|| -> CargoResult<Option<Resolve>> {
- let resolve: toml::Table = cargo_toml::parse_document(&s, f.path(), ws.config())?;
- let v: resolver::EncodableResolve = resolve.try_into()?;
+ let v: resolver::EncodableResolve = toml::from_str(&s)?;
Ok(Some(v.into_resolve(&s, ws)?))
})()
.with_context(|| format!("failed to parse lock file at: {}", f.path().display()))?;
diff --git a/src/tools/cargo/src/cargo/ops/mod.rs b/src/tools/cargo/src/cargo/ops/mod.rs
index d4ec442dd..13613eaf6 100644
--- a/src/tools/cargo/src/cargo/ops/mod.rs
+++ b/src/tools/cargo/src/cargo/ops/mod.rs
@@ -30,6 +30,7 @@ pub use self::registry::yank;
pub use self::registry::OwnersOptions;
pub use self::registry::PublishOpts;
pub use self::registry::RegistryCredentialConfig;
+pub use self::registry::RegistryOrIndex;
pub use self::resolve::{
add_overrides, get_resolved_packages, resolve_with_previous, resolve_ws, resolve_ws_with_opts,
WorkspaceResolve,
diff --git a/src/tools/cargo/src/cargo/ops/registry/login.rs b/src/tools/cargo/src/cargo/ops/registry/login.rs
index e52373734..e21dfe023 100644
--- a/src/tools/cargo/src/cargo/ops/registry/login.rs
+++ b/src/tools/cargo/src/cargo/ops/registry/login.rs
@@ -16,16 +16,23 @@ use cargo_credential::Secret;
use super::get_source_id;
use super::registry;
+use super::RegistryOrIndex;
pub fn registry_login(
config: &Config,
token_from_cmdline: Option<Secret<&str>>,
- reg: Option<&str>,
+ reg_or_index: Option<&RegistryOrIndex>,
args: &[&str],
) -> CargoResult<()> {
- let source_ids = get_source_id(config, None, reg)?;
-
- let login_url = match registry(config, token_from_cmdline.clone(), None, reg, false, None) {
+ let source_ids = get_source_id(config, reg_or_index)?;
+
+ let login_url = match registry(
+ config,
+ token_from_cmdline.clone(),
+ reg_or_index,
+ false,
+ None,
+ ) {
Ok((registry, _)) => Some(format!("{}/me", registry.host())),
Err(e) if e.is::<AuthorizationError>() => e
.downcast::<AuthorizationError>()
diff --git a/src/tools/cargo/src/cargo/ops/registry/logout.rs b/src/tools/cargo/src/cargo/ops/registry/logout.rs
index d1f080bae..fa0cbc539 100644
--- a/src/tools/cargo/src/cargo/ops/registry/logout.rs
+++ b/src/tools/cargo/src/cargo/ops/registry/logout.rs
@@ -8,9 +8,10 @@ use crate::CargoResult;
use crate::Config;
use super::get_source_id;
+use super::RegistryOrIndex;
-pub fn registry_logout(config: &Config, reg: Option<&str>) -> CargoResult<()> {
- let source_ids = get_source_id(config, None, reg)?;
+pub fn registry_logout(config: &Config, reg_or_index: Option<RegistryOrIndex>) -> CargoResult<()> {
+ let source_ids = get_source_id(config, reg_or_index.as_ref())?;
auth::logout(config, &source_ids.original)?;
Ok(())
}
diff --git a/src/tools/cargo/src/cargo/ops/registry/mod.rs b/src/tools/cargo/src/cargo/ops/registry/mod.rs
index 94ef1ead2..c82230a16 100644
--- a/src/tools/cargo/src/cargo/ops/registry/mod.rs
+++ b/src/tools/cargo/src/cargo/ops/registry/mod.rs
@@ -16,15 +16,15 @@ use std::task::Poll;
use anyhow::{bail, format_err, Context as _};
use cargo_credential::{Operation, Secret};
use crates_io::{self, Registry};
+use url::Url;
-use crate::core::source::Source;
use crate::core::SourceId;
+use crate::sources::source::Source;
use crate::sources::{RegistrySource, SourceConfigMap};
use crate::util::auth;
use crate::util::config::{Config, PathAndArgs};
use crate::util::errors::CargoResult;
use crate::util::network::http::http_handle;
-use crate::util::IntoUrl;
pub use self::login::registry_login;
pub use self::logout::registry_logout;
@@ -35,6 +35,19 @@ pub use self::publish::PublishOpts;
pub use self::search::search;
pub use self::yank::yank;
+/// Represents either `--registry` or `--index` argument, which is mutually exclusive.
+#[derive(Debug, Clone)]
+pub enum RegistryOrIndex {
+ Registry(String),
+ Index(Url),
+}
+
+impl RegistryOrIndex {
+ fn is_index(&self) -> bool {
+ matches!(self, RegistryOrIndex::Index(..))
+ }
+}
+
/// Registry settings loaded from config files.
///
/// This is loaded based on the `--registry` flag and the config settings.
@@ -103,14 +116,14 @@ impl RegistryCredentialConfig {
fn registry(
config: &Config,
token_from_cmdline: Option<Secret<&str>>,
- index: Option<&str>,
- registry: Option<&str>,
+ reg_or_index: Option<&RegistryOrIndex>,
force_update: bool,
token_required: Option<Operation<'_>>,
) -> CargoResult<(Registry, RegistrySourceIds)> {
- let source_ids = get_source_id(config, index, registry)?;
+ let source_ids = get_source_id(config, reg_or_index)?;
- if token_required.is_some() && index.is_some() && token_from_cmdline.is_none() {
+ let is_index = reg_or_index.map(|v| v.is_index()).unwrap_or_default();
+ if is_index && token_required.is_some() && token_from_cmdline.is_none() {
bail!("command-line argument --index requires --token to be specified");
}
if let Some(token) = token_from_cmdline {
@@ -145,6 +158,7 @@ fn registry(
None,
operation,
vec![],
+ false,
)?)
} else {
None
@@ -171,13 +185,12 @@ fn registry(
/// crates.io (such as index.crates.io), while the second is always the original source.
fn get_source_id(
config: &Config,
- index: Option<&str>,
- reg: Option<&str>,
+ reg_or_index: Option<&RegistryOrIndex>,
) -> CargoResult<RegistrySourceIds> {
- let sid = match (reg, index) {
- (None, None) => SourceId::crates_io(config)?,
- (_, Some(i)) => SourceId::for_registry(&i.into_url()?)?,
- (Some(r), None) => SourceId::alt_registry(config, r)?,
+ let sid = match reg_or_index {
+ None => SourceId::crates_io(config)?,
+ Some(RegistryOrIndex::Index(url)) => SourceId::for_registry(url)?,
+ Some(RegistryOrIndex::Registry(r)) => SourceId::alt_registry(config, r)?,
};
// Load source replacements that are built-in to Cargo.
let builtin_replacement_sid = SourceConfigMap::empty(config)?
@@ -186,7 +199,7 @@ fn get_source_id(
let replacement_sid = SourceConfigMap::new(config)?
.load(sid, &HashSet::new())?
.replaced_source_id();
- if reg.is_none() && index.is_none() && replacement_sid != builtin_replacement_sid {
+ if reg_or_index.is_none() && replacement_sid != builtin_replacement_sid {
// Neither --registry nor --index was passed and the user has configured source-replacement.
if let Some(replacement_name) = replacement_sid.alt_registry_key() {
bail!("crates-io is replaced with remote registry {replacement_name};\ninclude `--registry {replacement_name}` or `--registry crates-io`");
diff --git a/src/tools/cargo/src/cargo/ops/registry/owner.rs b/src/tools/cargo/src/cargo/ops/registry/owner.rs
index e29c6400b..3f49bb5bb 100644
--- a/src/tools/cargo/src/cargo/ops/registry/owner.rs
+++ b/src/tools/cargo/src/cargo/ops/registry/owner.rs
@@ -13,14 +13,15 @@ use crate::util::important_paths::find_root_manifest_for_wd;
use crate::CargoResult;
use crate::Config;
+use super::RegistryOrIndex;
+
pub struct OwnersOptions {
pub krate: Option<String>,
pub token: Option<Secret<String>>,
- pub index: Option<String>,
+ pub reg_or_index: Option<RegistryOrIndex>,
pub to_add: Option<Vec<String>>,
pub to_remove: Option<Vec<String>>,
pub list: bool,
- pub registry: Option<String>,
}
pub fn modify_owners(config: &Config, opts: &OwnersOptions) -> CargoResult<()> {
@@ -38,8 +39,7 @@ pub fn modify_owners(config: &Config, opts: &OwnersOptions) -> CargoResult<()> {
let (mut registry, _) = super::registry(
config,
opts.token.as_ref().map(Secret::as_deref),
- opts.index.as_deref(),
- opts.registry.as_deref(),
+ opts.reg_or_index.as_ref(),
true,
Some(operation),
)?;
diff --git a/src/tools/cargo/src/cargo/ops/registry/publish.rs b/src/tools/cargo/src/cargo/ops/registry/publish.rs
index 40ca9fd16..a88a0a30f 100644
--- a/src/tools/cargo/src/cargo/ops/registry/publish.rs
+++ b/src/tools/cargo/src/cargo/ops/registry/publish.rs
@@ -21,12 +21,12 @@ use crate::core::manifest::ManifestMetadata;
use crate::core::resolver::CliFeatures;
use crate::core::Dependency;
use crate::core::Package;
-use crate::core::QueryKind;
use crate::core::SourceId;
use crate::core::Workspace;
use crate::ops;
use crate::ops::PackageOpts;
use crate::ops::Packages;
+use crate::sources::source::QueryKind;
use crate::sources::SourceConfigMap;
use crate::sources::CRATES_IO_REGISTRY;
use crate::util::auth;
@@ -37,11 +37,12 @@ use crate::CargoResult;
use crate::Config;
use super::super::check_dep_has_version;
+use super::RegistryOrIndex;
pub struct PublishOpts<'cfg> {
pub config: &'cfg Config,
pub token: Option<Secret<String>>,
- pub index: Option<String>,
+ pub reg_or_index: Option<RegistryOrIndex>,
pub verify: bool,
pub allow_dirty: bool,
pub jobs: Option<JobsConfig>,
@@ -49,7 +50,6 @@ pub struct PublishOpts<'cfg> {
pub to_publish: ops::Packages,
pub targets: Vec<String>,
pub dry_run: bool,
- pub registry: Option<String>,
pub cli_features: CliFeatures,
}
@@ -76,7 +76,10 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
let (pkg, cli_features) = pkgs.pop().unwrap();
- let mut publish_registry = opts.registry.clone();
+ let mut publish_registry = match opts.reg_or_index.as_ref() {
+ Some(RegistryOrIndex::Registry(registry)) => Some(registry.clone()),
+ _ => None,
+ };
if let Some(ref allowed_registries) = *pkg.publish() {
if publish_registry.is_none() && allowed_registries.len() == 1 {
// If there is only one allowed registry, push to that one directly,
@@ -116,11 +119,16 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
let ver = pkg.version().to_string();
let operation = Operation::Read;
+ let reg_or_index = match opts.reg_or_index.clone() {
+ Some(RegistryOrIndex::Registry(_)) | None => {
+ publish_registry.map(RegistryOrIndex::Registry)
+ }
+ val => val,
+ };
let (mut registry, reg_ids) = super::registry(
opts.config,
opts.token.as_ref().map(Secret::as_deref),
- opts.index.as_deref(),
- publish_registry.as_deref(),
+ reg_or_index.as_ref(),
true,
Some(operation).filter(|_| !opts.dry_run),
)?;
@@ -161,6 +169,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
None,
operation,
vec![],
+ false,
)?));
}
@@ -353,6 +362,17 @@ fn transmit(
.to_string(),
registry: dep_registry,
explicit_name_in_toml: dep.explicit_name_in_toml().map(|s| s.to_string()),
+ artifact: dep.artifact().map(|artifact| {
+ artifact
+ .kinds()
+ .iter()
+ .map(|x| x.as_str().into_owned())
+ .collect()
+ }),
+ bindep_target: dep.artifact().and_then(|artifact| {
+ artifact.target().map(|target| target.as_str().to_owned())
+ }),
+ lib: dep.artifact().map_or(false, |artifact| artifact.is_lib()),
})
})
.collect::<CargoResult<Vec<NewCrateDependency>>>()?;
@@ -372,6 +392,7 @@ fn transmit(
ref links,
ref rust_version,
} = *manifest.metadata();
+ let rust_version = rust_version.as_ref().map(ToString::to_string);
let readme_content = readme
.as_ref()
.map(|readme| {
@@ -424,7 +445,7 @@ fn transmit(
license_file: license_file.clone(),
badges: badges.clone(),
links: links.clone(),
- rust_version: rust_version.clone(),
+ rust_version,
},
tarball,
)
diff --git a/src/tools/cargo/src/cargo/ops/registry/search.rs b/src/tools/cargo/src/cargo/ops/registry/search.rs
index 5e01ea98f..10b4d600e 100644
--- a/src/tools/cargo/src/cargo/ops/registry/search.rs
+++ b/src/tools/cargo/src/cargo/ops/registry/search.rs
@@ -6,23 +6,23 @@ use std::cmp;
use std::iter::repeat;
use anyhow::Context as _;
-use termcolor::Color;
-use termcolor::ColorSpec;
use url::Url;
+use crate::util::style;
use crate::util::truncate_with_ellipsis;
use crate::CargoResult;
use crate::Config;
+use super::RegistryOrIndex;
+
pub fn search(
query: &str,
config: &Config,
- index: Option<String>,
+ reg_or_index: Option<RegistryOrIndex>,
limit: u32,
- reg: Option<String>,
) -> CargoResult<()> {
let (mut registry, source_ids) =
- super::registry(config, None, index.as_deref(), reg.as_deref(), false, None)?;
+ super::registry(config, None, reg_or_index.as_ref(), false, None)?;
let (crates, total_crates) = registry.search(query, limit).with_context(|| {
format!(
"failed to retrieve search results from the registry at {}",
@@ -58,15 +58,12 @@ pub fn search(
};
let mut fragments = line.split(query).peekable();
while let Some(fragment) = fragments.next() {
- let _ = config.shell().write_stdout(fragment, &ColorSpec::new());
+ let _ = config.shell().write_stdout(fragment, &style::NOP);
if fragments.peek().is_some() {
- let _ = config.shell().write_stdout(
- query,
- &ColorSpec::new().set_bold(true).set_fg(Some(Color::Green)),
- );
+ let _ = config.shell().write_stdout(query, &style::GOOD);
}
}
- let _ = config.shell().write_stdout("\n", &ColorSpec::new());
+ let _ = config.shell().write_stdout("\n", &style::NOP);
}
let search_max_limit = 100;
@@ -76,7 +73,7 @@ pub fn search(
"... and {} crates more (use --limit N to see more)\n",
total_crates - limit
),
- &ColorSpec::new(),
+ &style::NOP,
);
} else if total_crates > limit && limit >= search_max_limit {
let extra = if source_ids.original.is_crates_io() {
@@ -87,7 +84,7 @@ pub fn search(
};
let _ = config.shell().write_stdout(
format_args!("... and {} crates more{}\n", total_crates - limit, extra),
- &ColorSpec::new(),
+ &style::NOP,
);
}
diff --git a/src/tools/cargo/src/cargo/ops/registry/yank.rs b/src/tools/cargo/src/cargo/ops/registry/yank.rs
index 8a961b990..2a258ea81 100644
--- a/src/tools/cargo/src/cargo/ops/registry/yank.rs
+++ b/src/tools/cargo/src/cargo/ops/registry/yank.rs
@@ -13,14 +13,15 @@ use crate::util::config::Config;
use crate::util::errors::CargoResult;
use crate::util::important_paths::find_root_manifest_for_wd;
+use super::RegistryOrIndex;
+
pub fn yank(
config: &Config,
krate: Option<String>,
version: Option<String>,
token: Option<Secret<String>>,
- index: Option<String>,
+ reg_or_index: Option<RegistryOrIndex>,
undo: bool,
- reg: Option<String>,
) -> CargoResult<()> {
let name = match krate {
Some(name) => name,
@@ -30,9 +31,8 @@ pub fn yank(
ws.current()?.package_id().name().to_string()
}
};
- let version = match version {
- Some(v) => v,
- None => bail!("a version must be specified to yank"),
+ let Some(version) = version else {
+ bail!("a version must be specified to yank")
};
let message = if undo {
@@ -50,8 +50,7 @@ pub fn yank(
let (mut registry, _) = super::registry(
config,
token.as_ref().map(Secret::as_deref),
- index.as_deref(),
- reg.as_deref(),
+ reg_or_index.as_ref(),
true,
Some(message),
)?;
diff --git a/src/tools/cargo/src/cargo/ops/resolve.rs b/src/tools/cargo/src/cargo/ops/resolve.rs
index 6246311a5..053098d55 100644
--- a/src/tools/cargo/src/cargo/ops/resolve.rs
+++ b/src/tools/cargo/src/cargo/ops/resolve.rs
@@ -49,8 +49,8 @@
//! [`Package`]: crate::core::package
//! [`Target`]: crate::core::Target
//! [`Manifest`]: crate::core::Manifest
-//! [`Source`]: crate::core::Source
-//! [`SourceMap`]: crate::core::SourceMap
+//! [`Source`]: crate::sources::source::Source
+//! [`SourceMap`]: crate::sources::source::SourceMap
//! [`PackageRegistry`]: crate::core::registry::PackageRegistry
//! [source implementations]: crate::sources
//! [`Downloads`]: crate::core::package::Downloads
@@ -69,6 +69,7 @@ use crate::core::{GitReference, PackageId, PackageIdSpec, PackageSet, SourceId,
use crate::ops;
use crate::sources::PathSource;
use crate::util::errors::CargoResult;
+use crate::util::RustVersion;
use crate::util::{profile, CanonicalUrl};
use anyhow::Context as _;
use std::collections::{HashMap, HashSet};
@@ -106,8 +107,10 @@ version. This may also occur with an optional dependency that is not enabled.";
/// This is a simple interface used by commands like `clean`, `fetch`, and
/// `package`, which don't specify any options or features.
pub fn resolve_ws<'a>(ws: &Workspace<'a>) -> CargoResult<(PackageSet<'a>, Resolve)> {
+ let max_rust_version = ws.rust_version();
+
let mut registry = PackageRegistry::new(ws.config())?;
- let resolve = resolve_with_registry(ws, &mut registry)?;
+ let resolve = resolve_with_registry(ws, &mut registry, max_rust_version)?;
let packages = get_resolved_packages(&resolve, registry)?;
Ok((packages, resolve))
}
@@ -124,12 +127,13 @@ pub fn resolve_ws<'a>(ws: &Workspace<'a>) -> CargoResult<(PackageSet<'a>, Resolv
/// members. In this case, `opts.all_features` must be `true`.
pub fn resolve_ws_with_opts<'cfg>(
ws: &Workspace<'cfg>,
- target_data: &RustcTargetData<'cfg>,
+ target_data: &mut RustcTargetData<'cfg>,
requested_targets: &[CompileKind],
cli_features: &CliFeatures,
specs: &[PackageIdSpec],
has_dev_units: HasDevUnits,
force_all_targets: ForceAllTargets,
+ max_rust_version: Option<&RustVersion>,
) -> CargoResult<WorkspaceResolve<'cfg>> {
let mut registry = PackageRegistry::new(ws.config())?;
let mut add_patches = true;
@@ -138,7 +142,7 @@ pub fn resolve_ws_with_opts<'cfg>(
} else if ws.require_optional_deps() {
// First, resolve the root_package's *listed* dependencies, as well as
// downloading and updating all remotes and such.
- let resolve = resolve_with_registry(ws, &mut registry)?;
+ let resolve = resolve_with_registry(ws, &mut registry, max_rust_version)?;
// No need to add patches again, `resolve_with_registry` has done it.
add_patches = false;
@@ -149,7 +153,7 @@ pub fn resolve_ws_with_opts<'cfg>(
add_overrides(&mut registry, ws)?;
- for &(ref replace_spec, ref dep) in ws.root_replace() {
+ for (replace_spec, dep) in ws.root_replace() {
if !resolve
.iter()
.any(|r| replace_spec.matches(r) && !dep.matches_id(r))
@@ -184,6 +188,7 @@ pub fn resolve_ws_with_opts<'cfg>(
None,
specs,
add_patches,
+ max_rust_version,
)?;
let pkg_set = get_resolved_packages(&resolved_with_overrides, registry)?;
@@ -235,6 +240,7 @@ pub fn resolve_ws_with_opts<'cfg>(
fn resolve_with_registry<'cfg>(
ws: &Workspace<'cfg>,
registry: &mut PackageRegistry<'cfg>,
+ max_rust_version: Option<&RustVersion>,
) -> CargoResult<Resolve> {
let prev = ops::load_pkg_lockfile(ws)?;
let mut resolve = resolve_with_previous(
@@ -246,6 +252,7 @@ fn resolve_with_registry<'cfg>(
None,
&[],
true,
+ max_rust_version,
)?;
if !ws.is_ephemeral() && ws.require_optional_deps() {
@@ -278,6 +285,7 @@ pub fn resolve_with_previous<'cfg>(
to_avoid: Option<&HashSet<PackageId>>,
specs: &[PackageIdSpec],
register_patches: bool,
+ max_rust_version: Option<&RustVersion>,
) -> CargoResult<Resolve> {
// We only want one Cargo at a time resolving a crate graph since this can
// involve a lot of frobbing of the global caches.
@@ -321,15 +329,12 @@ pub fn resolve_with_previous<'cfg>(
for patch in patches {
version_prefs.prefer_dependency(patch.clone());
}
- let previous = match previous {
- Some(r) => r,
- None => {
- let patches: Vec<_> = patches.iter().map(|p| (p, None)).collect();
- let unlock_ids = registry.patch(url, &patches)?;
- // Since nothing is locked, this shouldn't possibly return anything.
- assert!(unlock_ids.is_empty());
- continue;
- }
+ let Some(previous) = previous else {
+ let patches: Vec<_> = patches.iter().map(|p| (p, None)).collect();
+ let unlock_ids = registry.patch(url, &patches)?;
+ // Since nothing is locked, this shouldn't possibly return anything.
+ assert!(unlock_ids.is_empty());
+ continue;
};
// This is a list of pairs where the first element of the pair is
@@ -481,7 +486,7 @@ pub fn resolve_with_previous<'cfg>(
let replace = match previous {
Some(r) => root_replace
.iter()
- .map(|&(ref spec, ref dep)| {
+ .map(|(spec, dep)| {
for (&key, &val) in r.replacements().iter() {
if spec.matches(key) && dep.matches_id(val) && keep(&val) {
let mut dep = dep.clone();
@@ -505,6 +510,7 @@ pub fn resolve_with_previous<'cfg>(
ws.unstable_features()
.require(Feature::public_dependency())
.is_ok(),
+ max_rust_version,
)?;
let patches: Vec<_> = registry
.patches()
@@ -530,9 +536,8 @@ pub fn add_overrides<'a>(
ws: &Workspace<'a>,
) -> CargoResult<()> {
let config = ws.config();
- let paths = match config.get_list("paths")? {
- Some(list) => list,
- None => return Ok(()),
+ let Some(paths) = config.get_list("paths")? else {
+ return Ok(());
};
let paths = paths.val.iter().map(|(s, def)| {
@@ -603,7 +608,7 @@ fn register_previous_locks(
// Ok so we've been passed in a `keep` function which basically says "if I
// return `true` then this package wasn't listed for an update on the command
- // line". That is, if we run `cargo update -p foo` then `keep(bar)` will return
+ // line". That is, if we run `cargo update foo` then `keep(bar)` will return
// `true`, whereas `keep(foo)` will return `false` (roughly speaking).
//
// This isn't actually quite what we want, however. Instead we want to
@@ -613,7 +618,7 @@ fn register_previous_locks(
// * There's a crate `log`.
// * There's a crate `serde` which depends on `log`.
//
- // Let's say we then run `cargo update -p serde`. This may *also* want to
+ // Let's say we then run `cargo update serde`. This may *also* want to
// update the `log` dependency as our newer version of `serde` may have a
// new minimum version required for `log`. Now this isn't always guaranteed
// to work. What'll happen here is we *won't* lock the `log` dependency nor
@@ -623,23 +628,11 @@ fn register_previous_locks(
// however, nothing else in the dependency graph depends on `log` and the
// newer version of `serde` requires a new version of `log` it'll get pulled
// in (as we didn't accidentally lock it to an old version).
- //
- // Additionally, here we process all path dependencies listed in the previous
- // resolve. They can not only have their dependencies change but also
- // the versions of the package change as well. If this ends up happening
- // then we want to make sure we don't lock a package ID node that doesn't
- // actually exist. Note that we don't do transitive visits of all the
- // package's dependencies here as that'll be covered below to poison those
- // if they changed.
let mut avoid_locking = HashSet::new();
registry.add_to_yanked_whitelist(resolve.iter().filter(keep));
for node in resolve.iter() {
if !keep(&node) {
add_deps(resolve, node, &mut avoid_locking);
- } else if let Some(pkg) = path_pkg(node.source_id()) {
- if pkg.package_id() != node {
- avoid_locking.insert(node);
- }
}
}
@@ -732,6 +725,24 @@ fn register_previous_locks(
}
}
+ // Additionally, here we process all path dependencies listed in the previous
+ // resolve. They can not only have their dependencies change but also
+ // the versions of the package change as well. If this ends up happening
+ // then we want to make sure we don't lock a package ID node that doesn't
+ // actually exist. Note that we don't do transitive visits of all the
+ // package's dependencies here as that'll be covered below to poison those
+ // if they changed.
+ //
+ // This must come after all other `add_deps` calls to ensure it recursively walks the tree when
+ // called.
+ for node in resolve.iter() {
+ if let Some(pkg) = path_pkg(node.source_id()) {
+ if pkg.package_id() != node {
+ avoid_locking.insert(node);
+ }
+ }
+ }
+
// Alright now that we've got our new, fresh, shiny, and refined `keep`
// function let's put it to action. Take a look at the previous lock file,
// filter everything by this callback, and then shove everything else into
diff --git a/src/tools/cargo/src/cargo/ops/tree/graph.rs b/src/tools/cargo/src/cargo/ops/tree/graph.rs
index f0dad4e5d..31276f104 100644
--- a/src/tools/cargo/src/cargo/ops/tree/graph.rs
+++ b/src/tools/cargo/src/cargo/ops/tree/graph.rs
@@ -598,9 +598,8 @@ fn add_feature_rec(
package_index: usize,
) {
let feature_map = resolve.summary(package_id).features();
- let fvs = match feature_map.get(&feature_name) {
- Some(fvs) => fvs,
- None => return,
+ let Some(fvs) = feature_map.get(&feature_name) else {
+ return;
};
for fv in fvs {
match fv {
diff --git a/src/tools/cargo/src/cargo/ops/tree/mod.rs b/src/tools/cargo/src/cargo/ops/tree/mod.rs
index f397b95af..ce3bae8cc 100644
--- a/src/tools/cargo/src/cargo/ops/tree/mod.rs
+++ b/src/tools/cargo/src/cargo/ops/tree/mod.rs
@@ -135,7 +135,7 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
// TODO: Target::All is broken with -Zfeatures=itarget. To handle that properly,
// `FeatureResolver` will need to be taught what "all" means.
let requested_kinds = CompileKind::from_requested_targets(ws.config(), &requested_targets)?;
- let target_data = RustcTargetData::new(ws, &requested_kinds)?;
+ let mut target_data = RustcTargetData::new(ws, &requested_kinds)?;
let specs = opts.packages.to_package_id_specs(ws)?;
let has_dev = if opts
.edge_kinds
@@ -150,14 +150,16 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
} else {
ForceAllTargets::No
};
+ let max_rust_version = ws.rust_version();
let ws_resolve = ops::resolve_ws_with_opts(
ws,
- &target_data,
+ &mut target_data,
&requested_kinds,
&opts.cli_features,
&specs,
has_dev,
force_all,
+ max_rust_version,
)?;
let package_map: HashMap<PackageId, &Package> = ws_resolve
diff --git a/src/tools/cargo/src/cargo/sources/config.rs b/src/tools/cargo/src/cargo/sources/config.rs
index c51c1f009..cc7aa9925 100644
--- a/src/tools/cargo/src/cargo/sources/config.rs
+++ b/src/tools/cargo/src/cargo/sources/config.rs
@@ -4,7 +4,8 @@
//! structure usable by Cargo itself. Currently this is primarily used to map
//! sources to one another via the `replace-with` key in `.cargo/config`.
-use crate::core::{GitReference, PackageId, Source, SourceId};
+use crate::core::{GitReference, PackageId, SourceId};
+use crate::sources::source::Source;
use crate::sources::{ReplacedSource, CRATES_IO_REGISTRY};
use crate::util::config::{self, ConfigRelativePath, OptValue};
use crate::util::errors::CargoResult;
@@ -134,30 +135,26 @@ impl<'cfg> SourceConfigMap<'cfg> {
) -> CargoResult<Box<dyn Source + 'cfg>> {
debug!("loading: {}", id);
- let mut name = match self.id2name.get(&id) {
- Some(name) => name,
- None => return id.load(self.config, yanked_whitelist),
+ let Some(mut name) = self.id2name.get(&id) else {
+ return id.load(self.config, yanked_whitelist);
};
let mut cfg_loc = "";
let orig_name = name;
let new_id = loop {
- let cfg = match self.cfgs.get(name) {
- Some(cfg) => cfg,
- None => {
- // Attempt to interpret the source name as an alt registry name
- if let Ok(alt_id) = SourceId::alt_registry(self.config, name) {
- debug!("following pointer to registry {}", name);
- break alt_id.with_precise(id.precise().map(str::to_string));
- }
- bail!(
- "could not find a configured source with the \
+ let Some(cfg) = self.cfgs.get(name) else {
+ // Attempt to interpret the source name as an alt registry name
+ if let Ok(alt_id) = SourceId::alt_registry(self.config, name) {
+ debug!("following pointer to registry {}", name);
+ break alt_id.with_precise(id.precise().map(str::to_string));
+ }
+ bail!(
+ "could not find a configured source with the \
name `{}` when attempting to lookup `{}` \
(configuration in `{}`)",
- name,
- orig_name,
- cfg_loc
- );
- }
+ name,
+ orig_name,
+ cfg_loc
+ );
};
match &cfg.replace_with {
Some((s, c)) => {
@@ -242,7 +239,7 @@ restore the source replacement configuration to continue the build
let mut srcs = Vec::new();
if let Some(registry) = def.registry {
let url = url(&registry, &format!("source.{}.registry", name))?;
- srcs.push(SourceId::for_alt_registry(&url, &name)?);
+ srcs.push(SourceId::for_source_replacement_registry(&url, &name)?);
}
if let Some(local_registry) = def.local_registry {
let path = local_registry.resolve_path(self.config);
diff --git a/src/tools/cargo/src/cargo/sources/directory.rs b/src/tools/cargo/src/cargo/sources/directory.rs
index a527c6dd7..7195fd72d 100644
--- a/src/tools/cargo/src/cargo/sources/directory.rs
+++ b/src/tools/cargo/src/cargo/sources/directory.rs
@@ -3,8 +3,10 @@ use std::fmt::{self, Debug, Formatter};
use std::path::{Path, PathBuf};
use std::task::Poll;
-use crate::core::source::MaybePackage;
-use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary};
+use crate::core::{Dependency, Package, PackageId, SourceId, Summary};
+use crate::sources::source::MaybePackage;
+use crate::sources::source::QueryKind;
+use crate::sources::source::Source;
use crate::sources::PathSource;
use crate::util::errors::CargoResult;
use crate::util::Config;
@@ -221,9 +223,8 @@ impl<'cfg> Source for DirectorySource<'cfg> {
}
fn verify(&self, id: PackageId) -> CargoResult<()> {
- let (pkg, cksum) = match self.packages.get(&id) {
- Some(&(ref pkg, ref cksum)) => (pkg, cksum),
- None => anyhow::bail!("failed to find entry for `{}` in directory source", id),
+ let Some((pkg, cksum)) = self.packages.get(&id) else {
+ anyhow::bail!("failed to find entry for `{}` in directory source", id);
};
for (file, cksum) in cksum.files.iter() {
diff --git a/src/tools/cargo/src/cargo/sources/git/mod.rs b/src/tools/cargo/src/cargo/sources/git/mod.rs
index 5d9d2886e..4c01016c2 100644
--- a/src/tools/cargo/src/cargo/sources/git/mod.rs
+++ b/src/tools/cargo/src/cargo/sources/git/mod.rs
@@ -2,7 +2,7 @@
//!
//! Apparently, the most important type in this module is [`GitSource`].
//! [`utils`] provides libgit2 utilities like fetch and checkout, whereas
-//! [`oxide`] is the couterpart for gitoxide integration. [`known_hosts`]
+//! [`oxide`] is the counterpart for gitoxide integration. [`known_hosts`]
//! is the mitigation of [CVE-2022-46176].
//!
//! [CVE-2022-46176]: https://blog.rust-lang.org/2023/01/10/cve-2022-46176.html
diff --git a/src/tools/cargo/src/cargo/sources/git/oxide.rs b/src/tools/cargo/src/cargo/sources/git/oxide.rs
index ec4fcecdd..5fccdd0c6 100644
--- a/src/tools/cargo/src/cargo/sources/git/oxide.rs
+++ b/src/tools/cargo/src/cargo/sources/git/oxide.rs
@@ -353,7 +353,7 @@ pub fn cargo_config_to_gitoxide_overrides(config: &Config) -> CargoResult<Vec<BS
Ok(values)
}
-/// Reinitializes a given Git repository. This is useful when a Git repoistory
+/// Reinitializes a given Git repository. This is useful when a Git repository
/// seems corrupted and we want to start over.
pub fn reinitialize(git_dir: &Path) -> CargoResult<()> {
fn init(path: &Path, bare: bool) -> CargoResult<()> {
diff --git a/src/tools/cargo/src/cargo/sources/git/source.rs b/src/tools/cargo/src/cargo/sources/git/source.rs
index 10796562d..7af342f45 100644
--- a/src/tools/cargo/src/cargo/sources/git/source.rs
+++ b/src/tools/cargo/src/cargo/sources/git/source.rs
@@ -1,9 +1,12 @@
//! See [GitSource].
-use crate::core::source::{MaybePackage, QueryKind, Source, SourceId};
use crate::core::GitReference;
+use crate::core::SourceId;
use crate::core::{Dependency, Package, PackageId, Summary};
use crate::sources::git::utils::GitRemote;
+use crate::sources::source::MaybePackage;
+use crate::sources::source::QueryKind;
+use crate::sources::source::Source;
use crate::sources::PathSource;
use crate::util::errors::CargoResult;
use crate::util::hex::short_hash;
@@ -70,7 +73,7 @@ pub struct GitSource<'cfg> {
source_id: SourceId,
/// The underlying path source to discover packages inside the Git repository.
path_source: Option<PathSource<'cfg>>,
- /// The identifer of this source for Cargo's Git cache directory.
+ /// The identifier of this source for Cargo's Git cache directory.
/// See [`ident`] for more.
ident: String,
config: &'cfg Config,
@@ -120,7 +123,7 @@ impl<'cfg> GitSource<'cfg> {
}
/// Returns the packages discovered by this source. It may fetch the Git
- /// repository as well as walk the filesystem if package informations
+ /// repository as well as walk the filesystem if package information
/// haven't yet updated.
pub fn read_packages(&mut self) -> CargoResult<Vec<Package>> {
if self.path_source.is_none() {
diff --git a/src/tools/cargo/src/cargo/sources/git/utils.rs b/src/tools/cargo/src/cargo/sources/git/utils.rs
index 093631091..74690d30c 100644
--- a/src/tools/cargo/src/cargo/sources/git/utils.rs
+++ b/src/tools/cargo/src/cargo/sources/git/utils.rs
@@ -264,7 +264,7 @@ impl<'a> GitCheckout<'a> {
/// is done. Use [`GitCheckout::is_fresh`] to check.
///
/// * The `database` is where this checkout is from.
- /// * The `repo` will be the checked out Git repoistory.
+ /// * The `repo` will be the checked out Git repository.
fn new(
database: &'a GitDatabase,
revision: git2::Oid,
@@ -394,7 +394,7 @@ impl<'a> GitCheckout<'a> {
fn update_submodules(&self, cargo_config: &Config) -> CargoResult<()> {
return update_submodules(&self.repo, cargo_config, self.remote_url().as_str());
- /// Recusive helper for [`GitCheckout::update_submodules`].
+ /// Recursive helper for [`GitCheckout::update_submodules`].
fn update_submodules(
repo: &git2::Repository,
cargo_config: &Config,
@@ -444,9 +444,8 @@ impl<'a> GitCheckout<'a> {
// A submodule which is listed in .gitmodules but not actually
// checked out will not have a head id, so we should ignore it.
- let head = match child.head_id() {
- Some(head) => head,
- None => return Ok(()),
+ let Some(head) = child.head_id() else {
+ return Ok(());
};
// If the submodule hasn't been checked out yet, we need to
@@ -1087,7 +1086,7 @@ pub fn fetch(
debug!("fetch failed: {}", err);
if !repo_reinitialized.load(Ordering::Relaxed)
- // We check for errors that could occour if the configuration, refs or odb files are corrupted.
+ // We check for errors that could occur if the configuration, refs or odb files are corrupted.
// We don't check for errors related to writing as `gitoxide` is expected to create missing leading
// folder before writing files into it, or else not even open a directory as git repository (which is
// also handled here).
@@ -1313,16 +1312,12 @@ fn maybe_gc_repo(repo: &mut git2::Repository, config: &Config) -> CargoResult<()
/// filenames, so they never get cleaned up.
fn clean_repo_temp_files(repo: &git2::Repository) {
let path = repo.path().join("objects/pack/pack_git2_*");
- let pattern = match path.to_str() {
- Some(p) => p,
- None => {
- tracing::warn!("cannot convert {path:?} to a string");
- return;
- }
+ let Some(pattern) = path.to_str() else {
+ tracing::warn!("cannot convert {path:?} to a string");
+ return;
};
- let paths = match glob::glob(pattern) {
- Ok(paths) => paths,
- Err(_) => return,
+ let Ok(paths) = glob::glob(pattern) else {
+ return;
};
for path in paths {
if let Ok(path) = path {
@@ -1336,7 +1331,7 @@ fn clean_repo_temp_files(repo: &git2::Repository) {
}
}
-/// Reinitializes a given Git repository. This is useful when a Git repoistory
+/// Reinitializes a given Git repository. This is useful when a Git repository
/// seems corrupted and we want to start over.
fn reinitialize(repo: &mut git2::Repository) -> CargoResult<()> {
// Here we want to drop the current repository object pointed to by `repo`,
diff --git a/src/tools/cargo/src/cargo/sources/mod.rs b/src/tools/cargo/src/cargo/sources/mod.rs
index 81eda24ca..7da1d652d 100644
--- a/src/tools/cargo/src/cargo/sources/mod.rs
+++ b/src/tools/cargo/src/cargo/sources/mod.rs
@@ -1,6 +1,14 @@
-//! Implementations of `Source` trait.
+//! The trait for sources of Cargo packages and its built-in implementations.
//!
-//! Cargo provides several built-in implementations of [`Source`] trait. Namely,
+//! A source is a provider that contains source files and metadata of packages.
+//! It provides a number of methods to fetch those package information, for
+//! example, querying metadata or downloading files for a package. These
+//! information then can be used as dependencies for other Cargo packages.
+//!
+//! This module provides [`Source`][source::Source] trait as an abstraction of different sources,
+//! as well as [`SourceMap`][source::SourceMap] struct as a map of all available sources.
+//!
+//! Several built-in implementations of `Source` trait are provided. Namely,
//!
//! * [`RegistrySource`] --- A source that provides an index for people to query
//! a crate's metadata, and fetch files for a certain crate. crates.io falls
@@ -16,7 +24,6 @@
//! This module also contains [`SourceConfigMap`], which is effectively the
//! representation of the `[source.*]` value in Cargo configuration.
//!
-//! [`Source`]: crate::core::Source
//! [source replacement]: https://doc.rust-lang.org/nightly/cargo/reference/source-replacement.html
pub use self::config::SourceConfigMap;
@@ -32,3 +39,4 @@ pub mod git;
pub mod path;
pub mod registry;
pub mod replaced;
+pub mod source;
diff --git a/src/tools/cargo/src/cargo/sources/path.rs b/src/tools/cargo/src/cargo/sources/path.rs
index 1d8ffc35c..0cc639976 100644
--- a/src/tools/cargo/src/cargo/sources/path.rs
+++ b/src/tools/cargo/src/cargo/sources/path.rs
@@ -3,9 +3,11 @@ use std::fmt::{self, Debug, Formatter};
use std::path::{Path, PathBuf};
use std::task::Poll;
-use crate::core::source::MaybePackage;
-use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary};
+use crate::core::{Dependency, Package, PackageId, SourceId, Summary};
use crate::ops;
+use crate::sources::source::MaybePackage;
+use crate::sources::source::QueryKind;
+use crate::sources::source::Source;
use crate::util::{internal, CargoResult, Config};
use anyhow::Context as _;
use cargo_util::paths;
@@ -28,7 +30,7 @@ pub struct PathSource<'cfg> {
source_id: SourceId,
/// The root path of this source.
path: PathBuf,
- /// Whether this source has updated all package informations it may contain.
+ /// Whether this source has updated all package information it may contain.
updated: bool,
/// Packages that this sources has discovered.
packages: Vec<Package>,
@@ -95,7 +97,7 @@ impl<'cfg> PathSource<'cfg> {
}
/// Returns the packages discovered by this source. It may walk the
- /// filesystem if package informations haven't yet updated.
+ /// filesystem if package information haven't yet updated.
pub fn read_packages(&self) -> CargoResult<Vec<Package>> {
if self.updated {
Ok(self.packages.clone())
@@ -173,9 +175,8 @@ impl<'cfg> PathSource<'cfg> {
};
let filter = |path: &Path, is_dir: bool| {
- let relative_path = match path.strip_prefix(root) {
- Ok(p) => p,
- Err(_) => return false,
+ let Ok(relative_path) = path.strip_prefix(root) else {
+ return false;
};
let rel = relative_path.as_os_str();
diff --git a/src/tools/cargo/src/cargo/sources/registry/download.rs b/src/tools/cargo/src/cargo/sources/registry/download.rs
index 08940b3a1..9bf838625 100644
--- a/src/tools/cargo/src/cargo/sources/registry/download.rs
+++ b/src/tools/cargo/src/cargo/sources/registry/download.rs
@@ -85,6 +85,7 @@ pub(super) fn download(
None,
Operation::Read,
vec![],
+ true,
)?)
} else {
None
diff --git a/src/tools/cargo/src/cargo/sources/registry/http_remote.rs b/src/tools/cargo/src/cargo/sources/registry/http_remote.rs
index 52f6f392e..9fe76333b 100644
--- a/src/tools/cargo/src/cargo/sources/registry/http_remote.rs
+++ b/src/tools/cargo/src/cargo/sources/registry/http_remote.rs
@@ -335,7 +335,7 @@ impl<'cfg> HttpRegistry<'cfg> {
}),
RetryResult::Err(e) => Err(e),
RetryResult::Retry(sleep) => {
- debug!("download retry {:?} for {sleep}ms", download.path);
+ debug!(target: "network", "download retry {:?} for {sleep}ms", download.path);
self.downloads.sleeping.push(sleep, (download, handle));
continue;
}
@@ -547,11 +547,9 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
return Poll::Ready(Ok(LoadResponse::NotFound));
}
StatusCode::Unauthorized
- if !self.auth_required
- && path == Path::new(RegistryConfig::NAME)
- && self.config.cli_unstable().registry_auth =>
+ if !self.auth_required && path == Path::new(RegistryConfig::NAME) =>
{
- debug!("re-attempting request for config.json with authorization included.");
+ debug!(target: "network", "re-attempting request for config.json with authorization included.");
self.fresh.remove(path);
self.auth_required = true;
@@ -568,9 +566,11 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
}
}
Ok(challenge) => {
- debug!("ignoring non-Cargo challenge: {}", challenge.scheme)
+ debug!(target: "network", "ignoring non-Cargo challenge: {}", challenge.scheme)
+ }
+ Err(e) => {
+ debug!(target: "network", "failed to parse challenge: {}", e)
}
- Err(e) => debug!("failed to parse challenge: {}", e),
}
}
}
@@ -586,12 +586,13 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
}
.into());
if self.auth_required {
- return Poll::Ready(err.context(auth::AuthorizationError {
- sid: self.source_id.clone(),
- default_registry: self.config.default_registry()?,
- login_url: self.login_url.clone(),
- reason: auth::AuthorizationErrorReason::TokenRejected,
- }));
+ let auth_error = auth::AuthorizationError::new(
+ self.config,
+ self.source_id,
+ self.login_url.clone(),
+ auth::AuthorizationErrorReason::TokenRejected,
+ )?;
+ return Poll::Ready(err.context(auth_error));
} else {
return Poll::Ready(err);
}
@@ -609,16 +610,12 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
}
}
- if !self.config.cli_unstable().registry_auth {
- self.auth_required = false;
- }
-
// Looks like we're going to have to do a network request.
self.start_fetch()?;
let mut handle = http_handle(self.config)?;
let full_url = self.full_url(path);
- debug!("fetch {}", full_url);
+ debug!(target: "network", "fetch {}", full_url);
handle.get(true)?;
handle.url(&full_url)?;
handle.follow_location(true)?;
@@ -651,9 +648,10 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
self.login_url.as_ref(),
Operation::Read,
self.auth_error_headers.clone(),
+ true,
)?;
headers.append(&format!("Authorization: {}", authorization))?;
- trace!("including authorization for {}", full_url);
+ trace!(target: "network", "including authorization for {}", full_url);
}
handle.http_headers(headers)?;
@@ -662,7 +660,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
// We do that through this token. Each request (and associated response) gets one.
let token = self.downloads.next;
self.downloads.next += 1;
- debug!("downloading {} as {}", path.display(), token);
+ debug!(target: "network", "downloading {} as {}", path.display(), token);
let is_new = self.downloads.pending_paths.insert(path.to_path_buf());
assert!(is_new, "path queued for download more than once");
@@ -671,7 +669,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
// That thread-local is set up in `block_until_ready` when it calls self.multi.perform,
// which is what ultimately calls this method.
handle.write_function(move |buf| {
- trace!("{} - {} bytes of data", token, buf.len());
+ trace!(target: "network", "{} - {} bytes of data", token, buf.len());
tls::with(|downloads| {
if let Some(downloads) = downloads {
downloads.pending[&token]
@@ -721,10 +719,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
}
fn config(&mut self) -> Poll<CargoResult<Option<RegistryConfig>>> {
- let mut cfg = ready!(self.config()?).clone();
- if !self.config.cli_unstable().registry_auth {
- cfg.auth_required = false;
- }
+ let cfg = ready!(self.config()?).clone();
Poll::Ready(Ok(Some(cfg)))
}
@@ -772,7 +767,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
}
fn block_until_ready(&mut self) -> CargoResult<()> {
- trace!(
+ trace!(target: "network",
"block_until_ready: {} transfers pending",
self.downloads.pending.len()
);
@@ -787,7 +782,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
.perform()
.with_context(|| "failed to perform http requests")
})?;
- trace!("{} transfers remaining", remaining_in_multi);
+ trace!(target: "network", "{} transfers remaining", remaining_in_multi);
if remaining_in_multi + self.downloads.sleeping.len() as u32 == 0 {
return Ok(());
@@ -795,7 +790,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
if self.downloads.pending.is_empty() {
let delay = self.downloads.sleeping.time_to_next().unwrap();
- debug!("sleeping main thread for {delay:?}");
+ debug!(target: "network", "sleeping main thread for {delay:?}");
std::thread::sleep(delay);
} else {
// We have no more replies to provide the caller with,
diff --git a/src/tools/cargo/src/cargo/sources/registry/index.rs b/src/tools/cargo/src/cargo/sources/registry/index.rs
index 05bfe71af..ca1cf4069 100644
--- a/src/tools/cargo/src/cargo/sources/registry/index.rs
+++ b/src/tools/cargo/src/cargo/sources/registry/index.rs
@@ -85,13 +85,13 @@
//! [`RemoteRegistry`]: super::remote::RemoteRegistry
//! [`Dependency`]: crate::core::Dependency
-use crate::core::dependency::DepKind;
+use crate::core::dependency::{Artifact, DepKind};
use crate::core::Dependency;
use crate::core::{PackageId, SourceId, Summary};
use crate::sources::registry::{LoadResponse, RegistryData};
use crate::util::interning::InternedString;
use crate::util::IntoUrl;
-use crate::util::{internal, CargoResult, Config, Filesystem, OptVersionReq, ToSemver};
+use crate::util::{internal, CargoResult, Config, Filesystem, OptVersionReq, RustVersion};
use anyhow::bail;
use cargo_util::{paths, registry::make_dep_path};
use semver::Version;
@@ -189,11 +189,64 @@ enum MaybeIndexSummary {
/// from a line from a raw index file, or a JSON blob from on-disk index cache.
///
/// In addition to a full [`Summary`], we have information on whether it is `yanked`.
-pub struct IndexSummary {
- pub summary: Summary,
- pub yanked: bool,
- /// Schema version, see [`IndexPackage::v`].
- v: u32,
+#[derive(Clone, Debug)]
+pub enum IndexSummary {
+ /// Available for consideration
+ Candidate(Summary),
+ /// Yanked within its registry
+ Yanked(Summary),
+ /// Not available as we are offline and create is not downloaded yet
+ Offline(Summary),
+ /// From a newer schema version and is likely incomplete or inaccurate
+ Unsupported(Summary, u32),
+}
+
+impl IndexSummary {
+ /// Extract the summary from any variant
+ pub fn as_summary(&self) -> &Summary {
+ match self {
+ IndexSummary::Candidate(sum)
+ | IndexSummary::Yanked(sum)
+ | IndexSummary::Offline(sum)
+ | IndexSummary::Unsupported(sum, _) => sum,
+ }
+ }
+
+ /// Extract the summary from any variant
+ pub fn into_summary(self) -> Summary {
+ match self {
+ IndexSummary::Candidate(sum)
+ | IndexSummary::Yanked(sum)
+ | IndexSummary::Offline(sum)
+ | IndexSummary::Unsupported(sum, _) => sum,
+ }
+ }
+
+ /// Extract the package id from any variant
+ pub fn package_id(&self) -> PackageId {
+ match self {
+ IndexSummary::Candidate(sum)
+ | IndexSummary::Yanked(sum)
+ | IndexSummary::Offline(sum)
+ | IndexSummary::Unsupported(sum, _) => sum.package_id(),
+ }
+ }
+
+ /// Returns `true` if the index summary is [`Yanked`].
+ ///
+ /// [`Yanked`]: IndexSummary::Yanked
+ #[must_use]
+ pub fn is_yanked(&self) -> bool {
+ matches!(self, Self::Yanked(..))
+ }
+
+ /// Returns `true` if the index summary is [`Offline`].
+ ///
+ /// [`Offline`]: IndexSummary::Offline
+ #[must_use]
+ pub fn is_offline(&self) -> bool {
+ matches!(self, Self::Offline(..))
+ }
}
/// A representation of the cache on disk that Cargo maintains of summaries.
@@ -270,7 +323,7 @@ struct SummariesCache<'a> {
/// A single line in the index representing a single version of a package.
#[derive(Deserialize)]
pub struct IndexPackage<'a> {
- /// Name of the pacakge.
+ /// Name of the package.
name: InternedString,
/// The version of this dependency.
vers: Version,
@@ -305,7 +358,7 @@ pub struct IndexPackage<'a> {
///
/// Added in 2023 (see <https://github.com/rust-lang/crates.io/pull/6267>),
/// can be `None` if published before then or if not set in the manifest.
- rust_version: Option<InternedString>,
+ rust_version: Option<RustVersion>,
/// The schema version for this entry.
///
/// If this is None, it defaults to version `1`. Entries with unknown
@@ -313,6 +366,9 @@ pub struct IndexPackage<'a> {
///
/// Version `2` schema adds the `features2` field.
///
+ /// Version `3` schema adds `artifact`, `bindep_targes`, and `lib` for
+ /// artifact dependencies support.
+ ///
/// This provides a method to safely introduce changes to index entries
/// and allow older versions of cargo to ignore newer entries it doesn't
/// understand. This is honored as of 1.51, so unfortunately older
@@ -356,6 +412,10 @@ struct RegistryDependency<'a> {
///
/// [RFC 1977]: https://rust-lang.github.io/rfcs/1977-public-private-dependencies.html
public: Option<bool>,
+ artifact: Option<Vec<Cow<'a, str>>>,
+ bindep_target: Option<Cow<'a, str>>,
+ #[serde(default)]
+ lib: bool,
}
impl<'cfg> RegistryIndex<'cfg> {
@@ -378,13 +438,13 @@ impl<'cfg> RegistryIndex<'cfg> {
/// the index file, aka [`IndexSummary`].
pub fn hash(&mut self, pkg: PackageId, load: &mut dyn RegistryData) -> Poll<CargoResult<&str>> {
let req = OptVersionReq::exact(pkg.version());
- let summary = self.summaries(&pkg.name(), &req, load)?;
+ let summary = self.summaries(pkg.name(), &req, load)?;
let summary = ready!(summary)
- .filter(|s| s.summary.version() == pkg.version())
+ .filter(|s| s.package_id().version() == pkg.version())
.next();
Poll::Ready(Ok(summary
.ok_or_else(|| internal(format!("no hash listed for {}", pkg)))?
- .summary
+ .as_summary()
.checksum()
.ok_or_else(|| internal(format!("no hash listed for {}", pkg)))?))
}
@@ -400,19 +460,20 @@ impl<'cfg> RegistryIndex<'cfg> {
///
/// Internally there's quite a few layer of caching to amortize this cost
/// though since this method is called quite a lot on null builds in Cargo.
- pub fn summaries<'a, 'b>(
+ fn summaries<'a, 'b>(
&'a mut self,
- name: &str,
+ name: InternedString,
req: &'b OptVersionReq,
load: &mut dyn RegistryData,
) -> Poll<CargoResult<impl Iterator<Item = &'a IndexSummary> + 'b>>
where
'a: 'b,
{
+ let bindeps = self.config.cli_unstable().bindeps;
+
let source_id = self.source_id;
// First up parse what summaries we have available.
- let name = InternedString::new(name);
let summaries = ready!(self.load_summaries(name, load)?);
// Iterate over our summaries, extract all relevant ones which match our
@@ -426,24 +487,27 @@ impl<'cfg> RegistryIndex<'cfg> {
.versions
.iter_mut()
.filter_map(move |(k, v)| if req.matches(k) { Some(v) } else { None })
- .filter_map(move |maybe| match maybe.parse(raw_data, source_id) {
- Ok(summary) => Some(summary),
- Err(e) => {
- info!("failed to parse `{}` registry package: {}", name, e);
- None
- }
- })
- .filter(move |is| {
- if is.v > INDEX_V_MAX {
- debug!(
- "unsupported schema version {} ({} {})",
- is.v,
- is.summary.name(),
- is.summary.version()
- );
- false
- } else {
- true
+ .filter_map(move |maybe| {
+ match maybe.parse(raw_data, source_id, bindeps) {
+ Ok(sum @ IndexSummary::Candidate(_) | sum @ IndexSummary::Yanked(_)) => {
+ Some(sum)
+ }
+ Ok(IndexSummary::Unsupported(summary, v)) => {
+ debug!(
+ "unsupported schema version {} ({} {})",
+ v,
+ summary.name(),
+ summary.version()
+ );
+ None
+ }
+ Ok(IndexSummary::Offline(_)) => {
+ unreachable!("We do not check for off-line until later")
+ }
+ Err(e) => {
+ info!("failed to parse `{}` registry package: {}", name, e);
+ None
+ }
}
})))
}
@@ -458,7 +522,7 @@ impl<'cfg> RegistryIndex<'cfg> {
/// The actual kind index file being parsed depends on which kind of
/// [`RegistryData`] the `load` argument is given. For example, a
/// Git-based [`RemoteRegistry`] will first try a on-disk index cache
- /// file, and then try parsing registry raw index fomr Git repository.
+ /// file, and then try parsing registry raw index from Git repository.
///
/// In effect, this is intended to be a quite cheap operation.
///
@@ -507,7 +571,7 @@ impl<'cfg> RegistryIndex<'cfg> {
/// This is primarily used by [`Source::query`](super::Source).
pub fn query_inner(
&mut self,
- name: &str,
+ name: InternedString,
req: &OptVersionReq,
load: &mut dyn RegistryData,
yanked_whitelist: &HashSet<PackageId>,
@@ -524,14 +588,35 @@ impl<'cfg> RegistryIndex<'cfg> {
// then cargo will fail to download and an error message
// indicating that the required dependency is unavailable while
// offline will be displayed.
- if ready!(self.query_inner_with_online(name, req, load, yanked_whitelist, f, false)?)
- > 0
- {
+ let mut called = false;
+ let callback = &mut |s: IndexSummary| {
+ if !s.is_offline() {
+ called = true;
+ f(s.into_summary());
+ }
+ };
+ ready!(self.query_inner_with_online(
+ name,
+ req,
+ load,
+ yanked_whitelist,
+ callback,
+ false
+ )?);
+ if called {
return Poll::Ready(Ok(()));
}
}
- self.query_inner_with_online(name, req, load, yanked_whitelist, f, true)
- .map_ok(|_| ())
+ self.query_inner_with_online(
+ name,
+ req,
+ load,
+ yanked_whitelist,
+ &mut |s| {
+ f(s.into_summary());
+ },
+ true,
+ )
}
/// Inner implementation of [`Self::query_inner`]. Returns the number of
@@ -540,13 +625,13 @@ impl<'cfg> RegistryIndex<'cfg> {
/// The `online` controls whether Cargo can access the network when needed.
fn query_inner_with_online(
&mut self,
- name: &str,
+ name: InternedString,
req: &OptVersionReq,
load: &mut dyn RegistryData,
yanked_whitelist: &HashSet<PackageId>,
- f: &mut dyn FnMut(Summary),
+ f: &mut dyn FnMut(IndexSummary),
online: bool,
- ) -> Poll<CargoResult<usize>> {
+ ) -> Poll<CargoResult<()>> {
let source_id = self.source_id;
let summaries = ready!(self.summaries(name, req, load))?;
@@ -562,27 +647,20 @@ impl<'cfg> RegistryIndex<'cfg> {
// does not satisfy the requirements, then resolution will
// fail. Unfortunately, whether or not something is optional
// is not known here.
- .filter(|s| (online || load.is_crate_downloaded(s.summary.package_id())))
+ .map(|s| {
+ if online || load.is_crate_downloaded(s.package_id()) {
+ s.clone()
+ } else {
+ IndexSummary::Offline(s.as_summary().clone())
+ }
+ })
// Next filter out all yanked packages. Some yanked packages may
// leak through if they're in a whitelist (aka if they were
// previously in `Cargo.lock`
- .filter(|s| !s.yanked || yanked_whitelist.contains(&s.summary.package_id()))
- .map(|s| s.summary.clone());
-
- // Handle `cargo update --precise` here. If specified, our own source
- // will have a precise version listed of the form
- // `<pkg>=<p_req>o-><f_req>` where `<pkg>` is the name of a crate on
- // this source, `<p_req>` is the version installed and `<f_req> is the
- // version requested (argument to `--precise`).
- let precise = match source_id.precise() {
- Some(p) if p.starts_with(name) && p[name.len()..].starts_with('=') => {
- let mut vers = p[name.len() + 1..].splitn(2, "->");
- let current_vers = vers.next().unwrap().to_semver().unwrap();
- let requested_vers = vers.next().unwrap().to_semver().unwrap();
- Some((current_vers, requested_vers))
- }
- _ => None,
- };
+ .filter(|s| !s.is_yanked() || yanked_whitelist.contains(&s.package_id()));
+
+ // Handle `cargo update --precise` here.
+ let precise = source_id.precise_registry_version(name.as_str());
let summaries = summaries.filter(|s| match &precise {
Some((current, requested)) => {
if req.matches(current) {
@@ -590,7 +668,7 @@ impl<'cfg> RegistryIndex<'cfg> {
// by build metadata. This shouldn't be allowed, but since
// it is, this will honor it if requested. However, if not
// specified, then ignore it.
- let s_vers = s.version();
+ let s_vers = s.package_id().version();
match (s_vers.build.is_empty(), requested.build.is_empty()) {
(true, true) => s_vers == requested,
(true, false) => false,
@@ -610,12 +688,8 @@ impl<'cfg> RegistryIndex<'cfg> {
None => true,
});
- let mut count = 0;
- for summary in summaries {
- f(summary);
- count += 1;
- }
- Poll::Ready(Ok(count))
+ summaries.for_each(f);
+ Poll::Ready(Ok(()))
}
/// Looks into the summaries to check if a package has been yanked.
@@ -625,9 +699,9 @@ impl<'cfg> RegistryIndex<'cfg> {
load: &mut dyn RegistryData,
) -> Poll<CargoResult<bool>> {
let req = OptVersionReq::exact(pkg.version());
- let found = ready!(self.summaries(&pkg.name(), &req, load))?
- .filter(|s| s.summary.version() == pkg.version())
- .any(|summary| summary.yanked);
+ let found = ready!(self.summaries(pkg.name(), &req, load))?
+ .filter(|s| s.package_id().version() == pkg.version())
+ .any(|s| s.is_yanked());
Poll::Ready(Ok(found))
}
}
@@ -683,6 +757,8 @@ impl Summaries {
let response = ready!(load.load(root, relative, index_version.as_deref())?);
+ let bindeps = config.cli_unstable().bindeps;
+
match response {
LoadResponse::CacheValid => {
tracing::debug!("fast path for registry cache of {:?}", relative);
@@ -713,7 +789,7 @@ impl Summaries {
// allow future cargo implementations to break the
// interpretation of each line here and older cargo will simply
// ignore the new lines.
- let summary = match IndexSummary::parse(line, source_id) {
+ let summary = match IndexSummary::parse(line, source_id, bindeps) {
Ok(summary) => summary,
Err(e) => {
// This should only happen when there is an index
@@ -732,7 +808,7 @@ impl Summaries {
continue;
}
};
- let version = summary.summary.package_id().version().clone();
+ let version = summary.package_id().version().clone();
cache.versions.push((version.clone(), line));
ret.versions.insert(version, summary.into());
}
@@ -866,12 +942,17 @@ impl MaybeIndexSummary {
/// Does nothing if this is already `Parsed`, and otherwise the `raw_data`
/// passed in is sliced with the bounds in `Unparsed` and then actually
/// parsed.
- fn parse(&mut self, raw_data: &[u8], source_id: SourceId) -> CargoResult<&IndexSummary> {
+ fn parse(
+ &mut self,
+ raw_data: &[u8],
+ source_id: SourceId,
+ bindeps: bool,
+ ) -> CargoResult<&IndexSummary> {
let (start, end) = match self {
MaybeIndexSummary::Unparsed { start, end } => (*start, *end),
MaybeIndexSummary::Parsed(summary) => return Ok(summary),
};
- let summary = IndexSummary::parse(&raw_data[start..end], source_id)?;
+ let summary = IndexSummary::parse(&raw_data[start..end], source_id, bindeps)?;
*self = MaybeIndexSummary::Parsed(summary);
match self {
MaybeIndexSummary::Unparsed { .. } => unreachable!(),
@@ -892,7 +973,7 @@ impl IndexSummary {
///
/// The `line` provided is expected to be valid JSON. It is supposed to be
/// a [`IndexPackage`].
- fn parse(line: &[u8], source_id: SourceId) -> CargoResult<IndexSummary> {
+ fn parse(line: &[u8], source_id: SourceId, bindeps: bool) -> CargoResult<IndexSummary> {
// ****CAUTION**** Please be extremely careful with returning errors
// from this function. Entries that error are not included in the
// index cache, and can cause cargo to get confused when switching
@@ -925,11 +1006,20 @@ impl IndexSummary {
}
let mut summary = Summary::new(pkgid, deps, &features, links, rust_version)?;
summary.set_checksum(cksum);
- Ok(IndexSummary {
- summary,
- yanked: yanked.unwrap_or(false),
- v,
- })
+
+ let v_max = if bindeps {
+ INDEX_V_MAX + 1
+ } else {
+ INDEX_V_MAX
+ };
+
+ if v_max < v {
+ Ok(IndexSummary::Unsupported(summary, v))
+ } else if yanked.unwrap_or(false) {
+ Ok(IndexSummary::Yanked(summary))
+ } else {
+ Ok(IndexSummary::Candidate(summary))
+ }
}
}
@@ -947,6 +1037,9 @@ impl<'a> RegistryDependency<'a> {
registry,
package,
public,
+ artifact,
+ bindep_target,
+ lib,
} = self;
let id = if let Some(registry) = &registry {
@@ -986,6 +1079,11 @@ impl<'a> RegistryDependency<'a> {
dep.set_registry_id(id);
}
+ if let Some(artifacts) = artifact {
+ let artifact = Artifact::parse(&artifacts, lib, bindep_target.as_deref())?;
+ dep.set_artifact(artifact);
+ }
+
dep.set_optional(optional)
.set_default_features(default_features)
.set_features(features)
diff --git a/src/tools/cargo/src/cargo/sources/registry/local.rs b/src/tools/cargo/src/cargo/sources/registry/local.rs
index 68fc61a6c..84ed52c39 100644
--- a/src/tools/cargo/src/cargo/sources/registry/local.rs
+++ b/src/tools/cargo/src/cargo/sources/registry/local.rs
@@ -63,7 +63,7 @@ pub struct LocalRegistry<'cfg> {
/// Path where this local registry extract `.crate` tarballs to.
src_path: Filesystem,
config: &'cfg Config,
- /// Whether this source has updated all package informations it may contain.
+ /// Whether this source has updated all package information it may contain.
updated: bool,
/// Disables status messages.
quiet: bool,
diff --git a/src/tools/cargo/src/cargo/sources/registry/mod.rs b/src/tools/cargo/src/cargo/sources/registry/mod.rs
index c1ff8b12e..fb8f79817 100644
--- a/src/tools/cargo/src/cargo/sources/registry/mod.rs
+++ b/src/tools/cargo/src/cargo/sources/registry/mod.rs
@@ -201,14 +201,15 @@ use tar::Archive;
use tracing::debug;
use crate::core::dependency::Dependency;
-use crate::core::source::MaybePackage;
-use crate::core::{Package, PackageId, QueryKind, Source, SourceId, Summary};
+use crate::core::{Package, PackageId, SourceId, Summary};
+use crate::sources::source::MaybePackage;
+use crate::sources::source::QueryKind;
+use crate::sources::source::Source;
use crate::sources::PathSource;
use crate::util::hex;
+use crate::util::interning::InternedString;
use crate::util::network::PollExt;
-use crate::util::{
- restricted_names, CargoResult, Config, Filesystem, LimitErrorReader, OptVersionReq,
-};
+use crate::util::{restricted_names, CargoResult, Config, Filesystem, LimitErrorReader};
/// The `.cargo-ok` file is used to track if the source is already unpacked.
/// See [`RegistrySource::unpack_package`] for more.
@@ -251,7 +252,7 @@ pub struct RegistrySource<'cfg> {
/// yanked.
///
/// This is populated from the entries in `Cargo.lock` to ensure that
- /// `cargo update -p somepkg` won't unlock yanked entries in `Cargo.lock`.
+ /// `cargo update somepkg` won't unlock yanked entries in `Cargo.lock`.
/// Otherwise, the resolver would think that those entries no longer
/// exist, and it would trigger updates to unrelated packages.
yanked_whitelist: HashSet<PackageId>,
@@ -688,20 +689,14 @@ impl<'cfg> RegistrySource<'cfg> {
// After we've loaded the package configure its summary's `checksum`
// field with the checksum we know for this `PackageId`.
- let req = OptVersionReq::exact(package.version());
- let summary_with_cksum = self
+ let cksum = self
.index
- .summaries(&package.name(), &req, &mut *self.ops)?
+ .hash(package, &mut *self.ops)
.expect("a downloaded dep now pending!?")
- .map(|s| s.summary.clone())
- .filter(|s| s.version() == package.version())
- .next()
.expect("summary not found");
- if let Some(cksum) = summary_with_cksum.checksum() {
- pkg.manifest_mut()
- .summary_mut()
- .set_checksum(cksum.to_string());
- }
+ pkg.manifest_mut()
+ .summary_mut()
+ .set_checksum(cksum.to_string());
Ok(pkg)
}
@@ -723,7 +718,7 @@ impl<'cfg> Source for RegistrySource<'cfg> {
debug!("attempting query without update");
let mut called = false;
ready!(self.index.query_inner(
- &dep.package_name(),
+ dep.package_name(),
dep.version_req(),
&mut *self.ops,
&self.yanked_whitelist,
@@ -744,7 +739,7 @@ impl<'cfg> Source for RegistrySource<'cfg> {
} else {
let mut called = false;
ready!(self.index.query_inner(
- &dep.package_name(),
+ dep.package_name(),
dep.version_req(),
&mut *self.ops,
&self.yanked_whitelist,
@@ -774,13 +769,14 @@ impl<'cfg> Source for RegistrySource<'cfg> {
dep.package_name().replace('-', "_"),
dep.package_name().replace('_', "-"),
] {
- if name_permutation.as_str() == dep.package_name().as_str() {
+ let name_permutation = InternedString::new(&name_permutation);
+ if name_permutation == dep.package_name() {
continue;
}
any_pending |= self
.index
.query_inner(
- &name_permutation,
+ name_permutation,
dep.version_req(),
&mut *self.ops,
&self.yanked_whitelist,
diff --git a/src/tools/cargo/src/cargo/sources/registry/remote.rs b/src/tools/cargo/src/cargo/sources/registry/remote.rs
index 89927181f..39eb14dc0 100644
--- a/src/tools/cargo/src/cargo/sources/registry/remote.rs
+++ b/src/tools/cargo/src/cargo/sources/registry/remote.rs
@@ -59,7 +59,7 @@ pub struct RemoteRegistry<'cfg> {
/// A Git [tree object] to help this registry find crate metadata from the
/// underlying Git repository.
///
- /// This is stored here to prevent Git from repeatly creating a tree object
+ /// This is stored here to prevent Git from repeatedly creating a tree object
/// during each call into `load()`.
///
/// [tree object]: https://git-scm.com/book/en/v2/Git-Internals-Git-Objects#_tree_objects
@@ -70,7 +70,7 @@ pub struct RemoteRegistry<'cfg> {
head: Cell<Option<git2::Oid>>,
/// This stores sha value of the current HEAD commit for convenience.
current_sha: Cell<Option<InternedString>>,
- /// Whether this registry needs to update package informations.
+ /// Whether this registry needs to update package information.
///
/// See [`RemoteRegistry::mark_updated`] on how to make sure a registry
/// index is updated only once per session.
@@ -269,9 +269,8 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
}
let object = entry.to_object(repo)?;
- let blob = match object.as_blob() {
- Some(blob) => blob,
- None => anyhow::bail!("path `{}` is not a blob in the git repo", path.display()),
+ let Some(blob) = object.as_blob() else {
+ anyhow::bail!("path `{}` is not a blob in the git repo", path.display())
};
Ok(LoadResponse::Data {
@@ -307,10 +306,7 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
match ready!(self.load(Path::new(""), Path::new(RegistryConfig::NAME), None)?) {
LoadResponse::Data { raw_data, .. } => {
trace!("config loaded");
- let mut cfg: RegistryConfig = serde_json::from_slice(&raw_data)?;
- if !self.config.cli_unstable().registry_auth {
- cfg.auth_required = false;
- }
+ let cfg: RegistryConfig = serde_json::from_slice(&raw_data)?;
Poll::Ready(Ok(Some(cfg)))
}
_ => Poll::Ready(Ok(None)),
diff --git a/src/tools/cargo/src/cargo/sources/replaced.rs b/src/tools/cargo/src/cargo/sources/replaced.rs
index eef30e80c..f224e073d 100644
--- a/src/tools/cargo/src/cargo/sources/replaced.rs
+++ b/src/tools/cargo/src/cargo/sources/replaced.rs
@@ -1,5 +1,7 @@
-use crate::core::source::MaybePackage;
-use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary};
+use crate::core::{Dependency, Package, PackageId, SourceId, Summary};
+use crate::sources::source::MaybePackage;
+use crate::sources::source::QueryKind;
+use crate::sources::source::Source;
use crate::util::errors::CargoResult;
use std::task::Poll;
diff --git a/src/tools/cargo/src/cargo/core/source/mod.rs b/src/tools/cargo/src/cargo/sources/source.rs
index 2d1db1d53..5a3439e5d 100644
--- a/src/tools/cargo/src/cargo/core/source/mod.rs
+++ b/src/tools/cargo/src/cargo/sources/source.rs
@@ -1,30 +1,14 @@
-//! Fundamental types and traits for sources of Cargo packages.
-//!
-//! A source is a provider that contains source files and metadata of packages.
-//! It provides a number of methods to fetch those package informations, for
-//! example, querying metadata or downloading files for a package. These
-//! informations then can be used as dependencies for other Cargo packages.
-//!
-//! Notably, this module contains
-//!
-//! * [`Source`] trait as an abstraction of different sources
-//! * [`SourceMap`] struct as a map of all available sources
-//! * [`SourceId`] struct as an unique identifier for a certain source
-//!
-//! For implementations of `Source` trait, see [`crate::sources`].
+//! [`Source`] trait for sources of Cargo packages.
use std::collections::hash_map::HashMap;
use std::fmt;
use std::task::Poll;
use crate::core::package::PackageSet;
+use crate::core::SourceId;
use crate::core::{Dependency, Package, PackageId, Summary};
use crate::util::{CargoResult, Config};
-mod source_id;
-
-pub use self::source_id::{GitReference, SourceId};
-
/// An abstraction of different sources of Cargo packages.
///
/// The [`Source`] trait generalizes the API to interact with these providers.
@@ -63,7 +47,7 @@ pub trait Source {
/// Attempts to find the packages that match a dependency request.
///
/// Usually you should call [`Source::block_until_ready`] somewhere and
- /// wait until package informations become available. Otherwise any query
+ /// wait until package information become available. Otherwise any query
/// may return a [`Poll::Pending`].
///
/// The `f` argument is expected to get called when any [`Summary`] becomes available.
diff --git a/src/tools/cargo/src/cargo/util/auth/mod.rs b/src/tools/cargo/src/cargo/util/auth/mod.rs
index 60a356fa0..ea82dce0c 100644
--- a/src/tools/cargo/src/cargo/util/auth/mod.rs
+++ b/src/tools/cargo/src/cargo/util/auth/mod.rs
@@ -1,7 +1,7 @@
//! Registry authentication support.
use crate::{
- sources::CRATES_IO_REGISTRY,
+ core::features::cargo_docs_link,
util::{config::ConfigKey, CanonicalUrl, CargoResult, Config, IntoUrl},
};
use anyhow::{bail, Context as _};
@@ -74,11 +74,25 @@ impl RegistryConfigExtended {
}
/// Get the list of credential providers for a registry source.
-fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<String>>> {
+fn credential_provider(
+ config: &Config,
+ sid: &SourceId,
+ require_cred_provider_config: bool,
+ show_warnings: bool,
+) -> CargoResult<Vec<Vec<String>>> {
+ let warn = |message: String| {
+ if show_warnings {
+ config.shell().warn(message)
+ } else {
+ Ok(())
+ }
+ };
+
let cfg = registry_credential_config_raw(config, sid)?;
- let allow_cred_proc = config.cli_unstable().credential_process;
+ let mut global_provider_defined = true;
let default_providers = || {
- if allow_cred_proc {
+ global_provider_defined = false;
+ if config.cli_unstable().asymmetric_token {
// Enable the PASETO provider
vec![
vec!["cargo:token".to_string()],
@@ -90,7 +104,7 @@ fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<S
};
let global_providers = config
.get::<Option<Vec<Value<String>>>>("registry.global-credential-providers")?
- .filter(|p| !p.is_empty() && allow_cred_proc)
+ .filter(|p| !p.is_empty())
.map(|p| {
p.iter()
.rev()
@@ -101,29 +115,34 @@ fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<S
.unwrap_or_else(default_providers);
tracing::debug!(?global_providers);
- let providers = match cfg {
+ match cfg {
// If there's a specific provider configured for this registry, use it.
Some(RegistryConfig {
credential_provider: Some(provider),
token,
secret_key,
..
- }) if allow_cred_proc => {
+ }) => {
+ let provider = resolve_credential_alias(config, provider);
if let Some(token) = token {
- config.shell().warn(format!(
- "{sid} has a token configured in {} that will be ignored \
- because a credential-provider is configured for this registry`",
- token.definition
- ))?;
+ if provider[0] != "cargo:token" {
+ warn(format!(
+ "{sid} has a token configured in {} that will be ignored \
+ because this registry is configured to use credential-provider `{}`",
+ token.definition, provider[0],
+ ))?;
+ }
}
if let Some(secret_key) = secret_key {
- config.shell().warn(format!(
- "{sid} has a secret-key configured in {} that will be ignored \
- because a credential-provider is configured for this registry`",
- secret_key.definition
- ))?;
+ if provider[0] != "cargo:paseto" {
+ warn(format!(
+ "{sid} has a secret-key configured in {} that will be ignored \
+ because this registry is configured to use credential-provider `{}`",
+ secret_key.definition, provider[0],
+ ))?;
+ }
}
- vec![resolve_credential_alias(config, provider)]
+ return Ok(vec![provider]);
}
// Warning for both `token` and `secret-key`, stating which will be ignored
@@ -131,7 +150,7 @@ fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<S
token: Some(token),
secret_key: Some(secret_key),
..
- }) if allow_cred_proc => {
+ }) if config.cli_unstable().asymmetric_token => {
let token_pos = global_providers
.iter()
.position(|p| p.first().map(String::as_str) == Some("cargo:token"));
@@ -141,14 +160,14 @@ fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<S
match (token_pos, paseto_pos) {
(Some(token_pos), Some(paseto_pos)) => {
if token_pos < paseto_pos {
- config.shell().warn(format!(
+ warn(format!(
"{sid} has a `secret_key` configured in {} that will be ignored \
because a `token` is also configured, and the `cargo:token` provider is \
configured with higher precedence",
secret_key.definition
))?;
} else {
- config.shell().warn(format!("{sid} has a `token` configured in {} that will be ignored \
+ warn(format!("{sid} has a `token` configured in {} that will be ignored \
because a `secret_key` is also configured, and the `cargo:paseto` provider is \
configured with higher precedence", token.definition))?;
}
@@ -157,7 +176,6 @@ fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<S
// One or both of the below individual warnings will trigger
}
}
- global_providers
}
// Check if a `token` is configured that will be ignored.
@@ -168,39 +186,44 @@ fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<S
.iter()
.any(|p| p.first().map(String::as_str) == Some("cargo:token"))
{
- config.shell().warn(format!(
+ warn(format!(
"{sid} has a token configured in {} that will be ignored \
because the `cargo:token` credential provider is not listed in \
`registry.global-credential-providers`",
token.definition
))?;
}
- global_providers
}
// Check if a asymmetric token is configured that will be ignored.
Some(RegistryConfig {
secret_key: Some(token),
..
- }) if allow_cred_proc => {
+ }) if config.cli_unstable().asymmetric_token => {
if !global_providers
.iter()
.any(|p| p.first().map(String::as_str) == Some("cargo:paseto"))
{
- config.shell().warn(format!(
+ warn(format!(
"{sid} has a secret-key configured in {} that will be ignored \
because the `cargo:paseto` credential provider is not listed in \
`registry.global-credential-providers`",
token.definition
))?;
}
- global_providers
}
// If we couldn't find a registry-specific provider, use the fallback provider list.
- None | Some(RegistryConfig { .. }) => global_providers,
+ None | Some(RegistryConfig { .. }) => {}
};
- Ok(providers)
+ if !global_provider_defined && require_cred_provider_config {
+ bail!(
+ "authenticated registries require a credential-provider to be configured\n\
+ see {} for details",
+ cargo_docs_link("reference/registry-authentication.html")
+ );
+ }
+ Ok(global_providers)
}
/// Get the credential configuration for a `SourceId`.
@@ -319,10 +342,19 @@ fn registry_credential_config_raw_uncached(
/// Use the `[credential-alias]` table to see if the provider name has been aliased.
fn resolve_credential_alias(config: &Config, mut provider: PathAndArgs) -> Vec<String> {
if provider.args.is_empty() {
- let key = format!("credential-alias.{}", provider.path.raw_value());
- if let Ok(alias) = config.get::<PathAndArgs>(&key) {
+ let name = provider.path.raw_value();
+ let key = format!("credential-alias.{name}");
+ if let Ok(alias) = config.get::<Value<PathAndArgs>>(&key) {
tracing::debug!("resolving credential alias '{key}' -> '{alias:?}'");
- provider = alias;
+ if BUILT_IN_PROVIDERS.contains(&name) {
+ let _ = config.shell().warn(format!(
+ "credential-alias `{name}` (defined in `{}`) will be \
+ ignored because it would shadow a built-in credential-provider",
+ alias.definition
+ ));
+ } else {
+ provider = alias.val;
+ }
}
}
provider.args.insert(
@@ -356,14 +388,40 @@ impl fmt::Display for AuthorizationErrorReason {
#[derive(Debug)]
pub struct AuthorizationError {
/// Url that was attempted
- pub sid: SourceId,
+ sid: SourceId,
/// The `registry.default` config value.
- pub default_registry: Option<String>,
+ default_registry: Option<String>,
/// Url where the user could log in.
pub login_url: Option<Url>,
/// Specific reason indicating what failed
- pub reason: AuthorizationErrorReason,
+ reason: AuthorizationErrorReason,
+ /// Should the _TOKEN environment variable name be included when displaying this error?
+ display_token_env_help: bool,
}
+
+impl AuthorizationError {
+ pub fn new(
+ config: &Config,
+ sid: SourceId,
+ login_url: Option<Url>,
+ reason: AuthorizationErrorReason,
+ ) -> CargoResult<Self> {
+ // Only display the _TOKEN environment variable suggestion if the `cargo:token` credential
+ // provider is available for the source. Otherwise setting the environment variable will
+ // have no effect.
+ let display_token_env_help = credential_provider(config, &sid, false, false)?
+ .iter()
+ .any(|p| p.first().map(String::as_str) == Some("cargo:token"));
+ Ok(AuthorizationError {
+ sid,
+ default_registry: config.default_registry()?,
+ login_url,
+ reason,
+ display_token_env_help,
+ })
+ }
+}
+
impl Error for AuthorizationError {}
impl fmt::Display for AuthorizationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -373,20 +431,23 @@ impl fmt::Display for AuthorizationError {
} else {
""
};
- write!(
- f,
- "{}, please run `cargo login{args}`\nor use environment variable CARGO_REGISTRY_TOKEN",
- self.reason
- )
+ write!(f, "{}, please run `cargo login{args}`", self.reason)?;
+ if self.display_token_env_help {
+ write!(f, "\nor use environment variable CARGO_REGISTRY_TOKEN")?;
+ }
+ Ok(())
} else if let Some(name) = self.sid.alt_registry_key() {
let key = ConfigKey::from_str(&format!("registries.{name}.token"));
write!(
f,
- "{} for `{}`, please run `cargo login --registry {name}`\nor use environment variable {}",
+ "{} for `{}`, please run `cargo login --registry {name}`",
self.reason,
self.sid.display_registry_name(),
- key.as_env_key(),
- )
+ )?;
+ if self.display_token_env_help {
+ write!(f, "\nor use environment variable {}", key.as_env_key())?;
+ }
+ Ok(())
} else if self.reason == AuthorizationErrorReason::TokenMissing {
write!(
f,
@@ -412,7 +473,7 @@ my-registry = {{ index = "{}" }}
}
}
-// Store a token in the cache for future calls.
+/// Store a token in the cache for future calls.
pub fn cache_token_from_commandline(config: &Config, sid: &SourceId, token: Secret<&str>) {
let url = sid.canonical_url();
config.credential_cache().insert(
@@ -425,36 +486,48 @@ pub fn cache_token_from_commandline(config: &Config, sid: &SourceId, token: Secr
);
}
+/// List of credential providers built-in to Cargo.
+/// Keep in sync with the `match` in `credential_action`.
+static BUILT_IN_PROVIDERS: &[&'static str] = &[
+ "cargo:token",
+ "cargo:paseto",
+ "cargo:token-from-stdout",
+ "cargo:wincred",
+ "cargo:macos-keychain",
+ "cargo:libsecret",
+];
+
fn credential_action(
config: &Config,
sid: &SourceId,
action: Action<'_>,
headers: Vec<String>,
args: &[&str],
+ require_cred_provider_config: bool,
) -> CargoResult<CredentialResponse> {
- let name = if sid.is_crates_io() {
- Some(CRATES_IO_REGISTRY)
- } else {
- sid.alt_registry_key()
- };
+ let name = sid.alt_registry_key();
let registry = RegistryInfo {
index_url: sid.url().as_str(),
name,
headers,
};
- let providers = credential_provider(config, sid)?;
+ let providers = credential_provider(config, sid, require_cred_provider_config, true)?;
let mut any_not_found = false;
for provider in providers {
let args: Vec<&str> = provider
.iter()
.map(String::as_str)
- .chain(args.iter().map(|s| *s))
+ .chain(args.iter().copied())
.collect();
let process = args[0];
tracing::debug!("attempting credential provider: {args:?}");
+ // If the available built-in providers are changed, update the `BUILT_IN_PROVIDERS` list.
let provider: Box<dyn Credential> = match process {
"cargo:token" => Box::new(TokenCredential::new(config)),
- "cargo:paseto" => Box::new(PasetoCredential::new(config)),
+ "cargo:paseto" if config.cli_unstable().asymmetric_token => {
+ Box::new(PasetoCredential::new(config))
+ }
+ "cargo:paseto" => bail!("cargo:paseto requires -Zasymmetric-token"),
"cargo:token-from-stdout" => Box::new(BasicProcessCredential {}),
"cargo:wincred" => Box::new(cargo_credential_wincred::WindowsCredential {}),
"cargo:macos-keychain" => Box::new(cargo_credential_macos_keychain::MacKeychain {}),
@@ -501,15 +574,22 @@ pub fn auth_token(
login_url: Option<&Url>,
operation: Operation<'_>,
headers: Vec<String>,
+ require_cred_provider_config: bool,
) -> CargoResult<String> {
- match auth_token_optional(config, sid, operation, headers)? {
+ match auth_token_optional(
+ config,
+ sid,
+ operation,
+ headers,
+ require_cred_provider_config,
+ )? {
Some(token) => Ok(token.expose()),
- None => Err(AuthorizationError {
- sid: sid.clone(),
- default_registry: config.default_registry()?,
- login_url: login_url.cloned(),
- reason: AuthorizationErrorReason::TokenMissing,
- }
+ None => Err(AuthorizationError::new(
+ config,
+ *sid,
+ login_url.cloned(),
+ AuthorizationErrorReason::TokenMissing,
+ )?
.into()),
}
}
@@ -520,6 +600,7 @@ fn auth_token_optional(
sid: &SourceId,
operation: Operation<'_>,
headers: Vec<String>,
+ require_cred_provider_config: bool,
) -> CargoResult<Option<Secret<String>>> {
tracing::trace!("token requested for {}", sid.display_registry_name());
let mut cache = config.credential_cache();
@@ -540,7 +621,14 @@ fn auth_token_optional(
}
}
- let credential_response = credential_action(config, sid, Action::Get(operation), headers, &[]);
+ let credential_response = credential_action(
+ config,
+ sid,
+ Action::Get(operation),
+ headers,
+ &[],
+ require_cred_provider_config,
+ );
if let Some(e) = credential_response.as_ref().err() {
if let Some(e) = e.downcast_ref::<cargo_credential::Error>() {
if matches!(e, cargo_credential::Error::NotFound) {
@@ -561,7 +649,7 @@ fn auth_token_optional(
let token = Secret::from(token);
tracing::trace!("found token");
let expiration = match cache_control {
- CacheControl::Expires(expiration) => Some(expiration),
+ CacheControl::Expires { expiration } => Some(expiration),
CacheControl::Session => None,
CacheControl::Never | _ => return Ok(Some(token)),
};
@@ -579,7 +667,7 @@ fn auth_token_optional(
/// Log out from the given registry.
pub fn logout(config: &Config, sid: &SourceId) -> CargoResult<()> {
- let credential_response = credential_action(config, sid, Action::Logout, vec![], &[]);
+ let credential_response = credential_action(config, sid, Action::Logout, vec![], &[], false);
if let Some(e) = credential_response.as_ref().err() {
if let Some(e) = e.downcast_ref::<cargo_credential::Error>() {
if matches!(e, cargo_credential::Error::NotFound) {
@@ -608,7 +696,8 @@ pub fn login(
options: LoginOptions<'_>,
args: &[&str],
) -> CargoResult<()> {
- let credential_response = credential_action(config, sid, Action::Login(options), vec![], args)?;
+ let credential_response =
+ credential_action(config, sid, Action::Login(options), vec![], args, false)?;
let CredentialResponse::Login = credential_response else {
bail!("credential provider produced unexpected response for `login` request: {credential_response:?}")
};
diff --git a/src/tools/cargo/src/cargo/util/command_prelude.rs b/src/tools/cargo/src/cargo/util/command_prelude.rs
index bc707ef6f..bd8889bef 100644
--- a/src/tools/cargo/src/cargo/util/command_prelude.rs
+++ b/src/tools/cargo/src/cargo/util/command_prelude.rs
@@ -1,9 +1,11 @@
use crate::core::compiler::{BuildConfig, MessageFormat, TimingOutput};
use crate::core::resolver::CliFeatures;
use crate::core::{Edition, Workspace};
+use crate::ops::registry::RegistryOrIndex;
use crate::ops::{CompileFilter, CompileOptions, NewOptions, Packages, VersionControl};
use crate::util::important_paths::find_root_manifest_for_wd;
use crate::util::interning::InternedString;
+use crate::util::is_rustup;
use crate::util::restricted_names::is_glob_pattern;
use crate::util::toml::{StringOrVec, TomlProfile};
use crate::util::validate_package_name;
@@ -14,6 +16,7 @@ use crate::util::{
use crate::CargoResult;
use anyhow::bail;
use cargo_util::paths;
+use clap::builder::UnknownArgumentValueParser;
use std::ffi::{OsStr, OsString};
use std::path::Path;
use std::path::PathBuf;
@@ -25,6 +28,7 @@ pub use clap::{value_parser, Arg, ArgAction, ArgMatches};
pub use clap::Command;
use super::config::JobsConfig;
+use super::IntoUrl;
pub mod heading {
pub const PACKAGE_SELECTION: &str = "Package Selection";
@@ -82,17 +86,17 @@ pub trait CommandExt: Sized {
)
}
- fn arg_jobs(self) -> Self {
- self.arg_jobs_without_keep_going()._arg(
+ fn arg_parallel(self) -> Self {
+ self.arg_jobs()._arg(
flag(
"keep-going",
- "Do not abort the build as soon as there is an error (unstable)",
+ "Do not abort the build as soon as there is an error",
)
.help_heading(heading::COMPILATION_OPTIONS),
)
}
- fn arg_jobs_without_keep_going(self) -> Self {
+ fn arg_jobs(self) -> Self {
self._arg(
opt("jobs", "Number of parallel jobs, defaults to # of CPUs.")
.short('j')
@@ -102,6 +106,23 @@ pub trait CommandExt: Sized {
)
}
+ fn arg_unsupported_keep_going(self) -> Self {
+ let msg = "use `--no-fail-fast` to run as many tests as possible regardless of failure";
+ let value_parser = UnknownArgumentValueParser::suggest(msg);
+ self._arg(flag("keep-going", "").value_parser(value_parser).hide(true))
+ }
+
+ fn arg_redundant_default_mode(
+ self,
+ default_mode: &'static str,
+ command: &'static str,
+ supported_mode: &'static str,
+ ) -> Self {
+ let msg = format!("`--{default_mode}` is the default for `cargo {command}`; instead `--{supported_mode}` is supported");
+ let value_parser = UnknownArgumentValueParser::suggest(msg);
+ self._arg(flag(default_mode, "").value_parser(value_parser).hide(true))
+ }
+
fn arg_targets_all(
self,
lib: &'static str,
@@ -211,7 +232,10 @@ pub trait CommandExt: Sized {
}
fn arg_target_triple(self, target: &'static str) -> Self {
- self._arg(multi_opt("target", "TRIPLE", target).help_heading(heading::COMPILATION_OPTIONS))
+ self._arg(
+ optional_multi_opt("target", "TRIPLE", target)
+ .help_heading(heading::COMPILATION_OPTIONS),
+ )
}
fn arg_target_dir(self) -> Self {
@@ -253,8 +277,7 @@ pub trait CommandExt: Sized {
opt(
"vcs",
"Initialize a new repository for the given version \
- control system (git, hg, pijul, or fossil) or do not \
- initialize any version control at all (none), overriding \
+ control system, overriding \
a global configuration.",
)
.value_name("VCS")
@@ -276,12 +299,21 @@ pub trait CommandExt: Sized {
)
}
- fn arg_index(self) -> Self {
- self._arg(opt("index", "Registry index URL to upload the package to").value_name("INDEX"))
+ fn arg_registry(self, help: &'static str) -> Self {
+ self._arg(opt("registry", help).value_name("REGISTRY"))
+ }
+
+ fn arg_index(self, help: &'static str) -> Self {
+ // Always conflicts with `--registry`.
+ self._arg(
+ opt("index", help)
+ .value_name("INDEX")
+ .conflicts_with("registry"),
+ )
}
fn arg_dry_run(self, dry_run: &'static str) -> Self {
- self._arg(flag("dry-run", dry_run))
+ self._arg(flag("dry-run", dry_run).short('n'))
}
fn arg_ignore_rust_version(self) -> Self {
@@ -299,6 +331,18 @@ pub trait CommandExt: Sized {
}
fn arg_quiet(self) -> Self {
+ let unsupported_silent_arg = {
+ let value_parser = UnknownArgumentValueParser::suggest_arg("--quiet");
+ flag("silent", "")
+ .short('s')
+ .value_parser(value_parser)
+ .hide(true)
+ };
+ self._arg(flag("quiet", "Do not print cargo log messages").short('q'))
+ ._arg(unsupported_silent_arg)
+ }
+
+ fn arg_quiet_without_unknown_silent_arg_tip(self) -> Self {
self._arg(flag("quiet", "Do not print cargo log messages").short('q'))
}
@@ -431,11 +475,23 @@ pub trait ArgMatchesExt {
}
fn keep_going(&self) -> bool {
- self.flag("keep-going")
+ self.maybe_flag("keep-going")
}
- fn targets(&self) -> Vec<String> {
- self._values_of("target")
+ fn targets(&self) -> CargoResult<Vec<String>> {
+ if self.is_present_with_zero_values("target") {
+ let cmd = if is_rustup() {
+ "rustup target list"
+ } else {
+ "rustc --print target-list"
+ };
+ bail!(
+ "\"--target\" takes a target architecture as an argument.
+
+Run `{cmd}` to see possible targets."
+ );
+ }
+ Ok(self._values_of("target"))
}
fn get_profile_name(
@@ -453,7 +509,7 @@ pub trait ArgMatchesExt {
(Some(name @ ("dev" | "test" | "bench" | "check")), ProfileChecking::LegacyRustc)
// `cargo fix` and `cargo check` has legacy handling of this profile name
| (Some(name @ "test"), ProfileChecking::LegacyTestOnly) => {
- if self.flag("release") {
+ if self.maybe_flag("release") {
config.shell().warn(
"the `--release` flag should not be specified with the `--profile` flag\n\
The `--release` flag will be ignored.\n\
@@ -477,7 +533,11 @@ pub trait ArgMatchesExt {
)
};
- let name = match (self.flag("release"), self.flag("debug"), specified_profile) {
+ let name = match (
+ self.maybe_flag("release"),
+ self.maybe_flag("debug"),
+ specified_profile,
+ ) {
(false, false, None) => default,
(true, _, None | Some("release")) => "release",
(true, _, Some(name)) => return Err(conflict("release", "release", name)),
@@ -584,7 +644,7 @@ pub trait ArgMatchesExt {
config,
self.jobs()?,
self.keep_going(),
- &self.targets(),
+ &self.targets()?,
mode,
)?;
build_config.message_format = message_format.unwrap_or(MessageFormat::Human);
@@ -620,11 +680,6 @@ pub trait ArgMatchesExt {
}
}
- if build_config.keep_going {
- config
- .cli_unstable()
- .fail_if_stable_opt("--keep-going", 10496)?;
- }
if build_config.build_plan {
config
.cli_unstable()
@@ -718,29 +773,32 @@ pub trait ArgMatchesExt {
)
}
- fn registry(&self, config: &Config) -> CargoResult<Option<String>> {
+ fn registry_or_index(&self, config: &Config) -> CargoResult<Option<RegistryOrIndex>> {
let registry = self._value_of("registry");
let index = self._value_of("index");
let result = match (registry, index) {
- (None, None) => config.default_registry()?,
- (None, Some(_)) => {
- // If --index is set, then do not look at registry.default.
- None
- }
+ (None, None) => config.default_registry()?.map(RegistryOrIndex::Registry),
+ (None, Some(i)) => Some(RegistryOrIndex::Index(i.into_url()?)),
(Some(r), None) => {
validate_package_name(r, "registry name", "")?;
- Some(r.to_string())
+ Some(RegistryOrIndex::Registry(r.to_string()))
}
(Some(_), Some(_)) => {
- bail!("both `--index` and `--registry` should not be set at the same time")
+ // Should be guarded by clap
+ unreachable!("both `--index` and `--registry` should not be set at the same time")
}
};
Ok(result)
}
- fn index(&self) -> CargoResult<Option<String>> {
- let index = self._value_of("index").map(|s| s.to_string());
- Ok(index)
+ fn registry(&self, config: &Config) -> CargoResult<Option<String>> {
+ match self._value_of("registry").map(|s| s.to_string()) {
+ None => config.default_registry(),
+ Some(registry) => {
+ validate_package_name(&registry, "registry name", "")?;
+ Ok(Some(registry))
+ }
+ }
}
fn check_optional_opts(
@@ -777,6 +835,8 @@ pub trait ArgMatchesExt {
fn flag(&self, name: &str) -> bool;
+ fn maybe_flag(&self, name: &str) -> bool;
+
fn _value_of(&self, name: &str) -> Option<&str>;
fn _values_of(&self, name: &str) -> Vec<String>;
@@ -797,6 +857,17 @@ impl<'a> ArgMatchesExt for ArgMatches {
.unwrap_or(false)
}
+ // This works around before an upstream fix in clap for `UnknownArgumentValueParser` accepting
+ // generics arguments. `flag()` cannot be used with `--keep-going` at this moment due to
+ // <https://github.com/clap-rs/clap/issues/5081>.
+ fn maybe_flag(&self, name: &str) -> bool {
+ self.try_get_one::<bool>(name)
+ .ok()
+ .flatten()
+ .copied()
+ .unwrap_or_default()
+ }
+
fn _value_of(&self, name: &str) -> Option<&str> {
ignore_unknown(self.try_get_one::<String>(name)).map(String::as_str)
}
diff --git a/src/tools/cargo/src/cargo/util/config/de.rs b/src/tools/cargo/src/cargo/util/config/de.rs
index a9147ab03..e12a2d0b0 100644
--- a/src/tools/cargo/src/cargo/util/config/de.rs
+++ b/src/tools/cargo/src/cargo/util/config/de.rs
@@ -216,9 +216,8 @@ impl<'config> ConfigMapAccess<'config> {
// `CARGO_PROFILE_DEV_PACKAGE_`
let env_prefix = format!("{}_", de.key.as_env_key());
for env_key in de.config.env_keys() {
- if env_key.starts_with(&env_prefix) {
- // `CARGO_PROFILE_DEV_PACKAGE_bar_OPT_LEVEL = 3`
- let rest = &env_key[env_prefix.len()..];
+ // `CARGO_PROFILE_DEV_PACKAGE_bar_OPT_LEVEL = 3`
+ if let Some(rest) = env_key.strip_prefix(&env_prefix) {
// `rest = bar_OPT_LEVEL`
let part = rest.splitn(2, '_').next().unwrap();
// `part = "bar"`
diff --git a/src/tools/cargo/src/cargo/util/config/key.rs b/src/tools/cargo/src/cargo/util/config/key.rs
index 228d85844..cd1901140 100644
--- a/src/tools/cargo/src/cargo/util/config/key.rs
+++ b/src/tools/cargo/src/cargo/util/config/key.rs
@@ -49,7 +49,7 @@ impl ConfigKey {
/// equivalent to accessing a sub-table in TOML.
///
/// Note that this considers `name` to be case-insensitive, meaning that the
- /// corrseponding toml key is appended with this `name` as-is and the
+ /// corresponding toml key is appended with this `name` as-is and the
/// corresponding env key is appended with `name` after transforming it to
/// uppercase characters.
pub fn push(&mut self, name: &str) {
diff --git a/src/tools/cargo/src/cargo/util/config/mod.rs b/src/tools/cargo/src/cargo/util/config/mod.rs
index cf977d38d..b87f98afd 100644
--- a/src/tools/cargo/src/cargo/util/config/mod.rs
+++ b/src/tools/cargo/src/cargo/util/config/mod.rs
@@ -70,6 +70,8 @@ use crate::core::compiler::rustdoc::RustdocExternMap;
use crate::core::shell::Verbosity;
use crate::core::{features, CliUnstable, Shell, SourceId, Workspace, WorkspaceRootConfig};
use crate::ops::RegistryCredentialConfig;
+use crate::sources::CRATES_IO_INDEX;
+use crate::sources::CRATES_IO_REGISTRY;
use crate::util::errors::CargoResult;
use crate::util::network::http::configure_http_handle;
use crate::util::network::http::http_handle;
@@ -84,6 +86,7 @@ use curl::easy::Easy;
use lazycell::LazyCell;
use serde::de::IntoDeserializer as _;
use serde::Deserialize;
+use serde_untagged::UntaggedEnumVisitor;
use time::OffsetDateTime;
use toml_edit::Item;
use url::Url;
@@ -621,9 +624,8 @@ impl Config {
)));
}
let mut parts = key.parts().enumerate();
- let mut val = match vals.get(parts.next().unwrap().1) {
- Some(val) => val,
- None => return Ok(None),
+ let Some(mut val) = vals.get(parts.next().unwrap().1) else {
+ return Ok(None);
};
for (i, part) in parts {
match val {
@@ -905,12 +907,9 @@ impl Config {
key: &ConfigKey,
output: &mut Vec<(String, Definition)>,
) -> CargoResult<()> {
- let env_val = match self.env.get_str(key.as_env_key()) {
- Some(v) => v,
- None => {
- self.check_environment_key_case_mismatch(key);
- return Ok(());
- }
+ let Some(env_val) = self.env.get_str(key.as_env_key()) else {
+ self.check_environment_key_case_mismatch(key);
+ return Ok(());
};
let def = Definition::Environment(key.as_env_key().to_string());
@@ -938,6 +937,7 @@ impl Config {
.map(|s| (s.to_string(), def.clone())),
);
}
+ output.sort_by(|a, b| a.1.cmp(&b.1));
Ok(())
}
@@ -1259,9 +1259,8 @@ impl Config {
};
(path.to_string(), abs_path, def.clone())
};
- let table = match cv {
- CV::Table(table, _def) => table,
- _ => unreachable!(),
+ let CV::Table(table, _def) = cv else {
+ unreachable!()
};
let owned;
let include = if remove {
@@ -1300,9 +1299,8 @@ impl Config {
/// Parses the CLI config args and returns them as a table.
pub(crate) fn cli_args_as_table(&self) -> CargoResult<ConfigValue> {
let mut loaded_args = CV::Table(HashMap::new(), Definition::Cli(None));
- let cli_args = match &self.cli_config {
- Some(cli_args) => cli_args,
- None => return Ok(loaded_args),
+ let Some(cli_args) = &self.cli_config else {
+ return Ok(loaded_args);
};
let mut seen = HashSet::new();
for arg in cli_args {
@@ -1448,9 +1446,8 @@ impl Config {
/// Add config arguments passed on the command line.
fn merge_cli_args(&mut self) -> CargoResult<()> {
- let loaded_map = match self.cli_args_as_table()? {
- CV::Table(table, _def) => table,
- _ => unreachable!(),
+ let CV::Table(loaded_map, _def) = self.cli_args_as_table()? else {
+ unreachable!()
};
let values = self.values_mut()?;
for (key, value) in loaded_map.into_iter() {
@@ -1551,7 +1548,10 @@ impl Config {
)
})
} else {
- bail!("no index found for registry: `{}`", registry);
+ bail!(
+ "registry index was not found in any configuration: `{}`",
+ registry
+ );
}
}
@@ -1594,17 +1594,15 @@ impl Config {
}
let home_path = self.home_path.clone().into_path_unlocked();
- let credentials = match self.get_file_path(&home_path, "credentials", true)? {
- Some(credentials) => credentials,
- None => return Ok(()),
+ let Some(credentials) = self.get_file_path(&home_path, "credentials", true)? else {
+ return Ok(());
};
let mut value = self.load_file(&credentials)?;
// Backwards compatibility for old `.cargo/credentials` layout.
{
- let (value_map, def) = match value {
- CV::Table(ref mut value, ref def) => (value, def),
- _ => unreachable!(),
+ let CV::Table(ref mut value_map, ref def) = value else {
+ unreachable!();
};
if let Some(token) = value_map.remove("token") {
@@ -1838,11 +1836,17 @@ impl Config {
target::load_target_triple(self, target)
}
- pub fn crates_io_source_id<F>(&self, f: F) -> CargoResult<SourceId>
- where
- F: FnMut() -> CargoResult<SourceId>,
- {
- Ok(*(self.crates_io_source_id.try_borrow_with(f)?))
+ /// Returns the cached [`SourceId`] corresponding to the main repository.
+ ///
+ /// This is the main cargo registry by default, but it can be overridden in
+ /// a `.cargo/config.toml`.
+ pub fn crates_io_source_id(&self) -> CargoResult<SourceId> {
+ let source_id = self.crates_io_source_id.try_borrow_with(|| {
+ self.check_registry_index_not_set()?;
+ let url = CRATES_IO_INDEX.into_url().unwrap();
+ SourceId::for_alt_registry(&url, CRATES_IO_REGISTRY)
+ })?;
+ Ok(*source_id)
}
pub fn creation_time(&self) -> Instant {
@@ -2106,8 +2110,8 @@ impl ConfigValue {
/// Merge the given value into self.
///
- /// If `force` is true, primitive (non-container) types will override existing values.
- /// If false, the original will be kept and the new value ignored.
+ /// If `force` is true, primitive (non-container) types will override existing values
+ /// of equal priority. For arrays, incoming values of equal priority will be placed later.
///
/// Container types (tables and arrays) are merged with existing values.
///
@@ -2115,7 +2119,13 @@ impl ConfigValue {
fn merge(&mut self, from: ConfigValue, force: bool) -> CargoResult<()> {
match (self, from) {
(&mut CV::List(ref mut old, _), CV::List(ref mut new, _)) => {
- old.extend(mem::take(new).into_iter());
+ if force {
+ old.append(new);
+ } else {
+ new.append(old);
+ mem::swap(new, old);
+ }
+ old.sort_by(|a, b| a.1.cmp(&b.1));
}
(&mut CV::Table(ref mut old, _), CV::Table(ref mut new, _)) => {
for (key, value) in mem::take(new) {
@@ -2446,13 +2456,24 @@ impl CargoFutureIncompatConfig {
/// ssl-version.min = "tlsv1.2"
/// ssl-version.max = "tlsv1.3"
/// ```
-#[derive(Clone, Debug, Deserialize, PartialEq)]
-#[serde(untagged)]
+#[derive(Clone, Debug, PartialEq)]
pub enum SslVersionConfig {
Single(String),
Range(SslVersionConfigRange),
}
+impl<'de> Deserialize<'de> for SslVersionConfig {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ UntaggedEnumVisitor::new()
+ .string(|single| Ok(SslVersionConfig::Single(single.to_owned())))
+ .map(|map| map.deserialize().map(SslVersionConfig::Range))
+ .deserialize(deserializer)
+ }
+}
+
#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct SslVersionConfigRange {
pub min: Option<String>,
@@ -2486,13 +2507,24 @@ pub struct CargoSshConfig {
/// [build]
/// jobs = "default" # Currently only support "default".
/// ```
-#[derive(Debug, Deserialize, Clone)]
-#[serde(untagged)]
+#[derive(Debug, Clone)]
pub enum JobsConfig {
Integer(i32),
String(String),
}
+impl<'de> Deserialize<'de> for JobsConfig {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ UntaggedEnumVisitor::new()
+ .i32(|int| Ok(JobsConfig::Integer(int)))
+ .string(|string| Ok(JobsConfig::String(string.to_owned())))
+ .deserialize(deserializer)
+ }
+}
+
#[derive(Debug, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct CargoBuildConfig {
@@ -2527,13 +2559,24 @@ pub struct BuildTargetConfig {
inner: Value<BuildTargetConfigInner>,
}
-#[derive(Debug, Deserialize)]
-#[serde(untagged)]
+#[derive(Debug)]
enum BuildTargetConfigInner {
One(String),
Many(Vec<String>),
}
+impl<'de> Deserialize<'de> for BuildTargetConfigInner {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ UntaggedEnumVisitor::new()
+ .string(|one| Ok(BuildTargetConfigInner::One(one.to_owned())))
+ .seq(|many| many.deserialize().map(BuildTargetConfigInner::Many))
+ .deserialize(deserializer)
+ }
+}
+
impl BuildTargetConfig {
/// Gets values of `build.target` as a list of strings.
pub fn values(&self, config: &Config) -> CargoResult<Vec<String>> {
@@ -2645,19 +2688,44 @@ where
deserializer.deserialize_option(ProgressVisitor)
}
-#[derive(Debug, Deserialize)]
-#[serde(untagged)]
+#[derive(Debug)]
enum EnvConfigValueInner {
Simple(String),
WithOptions {
value: String,
- #[serde(default)]
force: bool,
- #[serde(default)]
relative: bool,
},
}
+impl<'de> Deserialize<'de> for EnvConfigValueInner {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ #[derive(Deserialize)]
+ struct WithOptions {
+ value: String,
+ #[serde(default)]
+ force: bool,
+ #[serde(default)]
+ relative: bool,
+ }
+
+ UntaggedEnumVisitor::new()
+ .string(|simple| Ok(EnvConfigValueInner::Simple(simple.to_owned())))
+ .map(|map| {
+ let with_options: WithOptions = map.deserialize()?;
+ Ok(EnvConfigValueInner::WithOptions {
+ value: with_options.value,
+ force: with_options.force,
+ relative: with_options.relative,
+ })
+ })
+ .deserialize(deserializer)
+ }
+}
+
#[derive(Debug, Deserialize)]
#[serde(transparent)]
pub struct EnvConfigValue {
diff --git a/src/tools/cargo/src/cargo/util/config/target.rs b/src/tools/cargo/src/cargo/util/config/target.rs
index b8aaf906d..6d6a6beff 100644
--- a/src/tools/cargo/src/cargo/util/config/target.rs
+++ b/src/tools/cargo/src/cargo/util/config/target.rs
@@ -12,6 +12,7 @@ use std::path::PathBuf;
pub struct TargetCfgConfig {
pub runner: OptValue<PathAndArgs>,
pub rustflags: OptValue<StringList>,
+ pub linker: OptValue<ConfigRelativePath>,
// This is here just to ignore fields from normal `TargetConfig` because
// all `[target]` tables are getting deserialized, whether they start with
// `cfg(` or not.
diff --git a/src/tools/cargo/src/cargo/util/config/value.rs b/src/tools/cargo/src/cargo/util/config/value.rs
index a70d75a07..7232bf39e 100644
--- a/src/tools/cargo/src/cargo/util/config/value.rs
+++ b/src/tools/cargo/src/cargo/util/config/value.rs
@@ -10,6 +10,7 @@
use crate::util::config::Config;
use serde::de;
+use std::cmp::Ordering;
use std::fmt;
use std::marker;
use std::mem;
@@ -63,6 +64,24 @@ pub enum Definition {
Cli(Option<PathBuf>),
}
+impl PartialOrd for Definition {
+ fn partial_cmp(&self, other: &Definition) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for Definition {
+ fn cmp(&self, other: &Definition) -> Ordering {
+ if mem::discriminant(self) == mem::discriminant(other) {
+ Ordering::Equal
+ } else if self.is_higher_priority(other) {
+ Ordering::Greater
+ } else {
+ Ordering::Less
+ }
+ }
+}
+
impl Definition {
/// Root directory where this is defined.
///
diff --git a/src/tools/cargo/src/cargo/util/credential/paseto.rs b/src/tools/cargo/src/cargo/util/credential/paseto.rs
index 329d1f11c..bd49af98a 100644
--- a/src/tools/cargo/src/cargo/util/credential/paseto.rs
+++ b/src/tools/cargo/src/cargo/util/credential/paseto.rs
@@ -200,8 +200,17 @@ impl<'a> Credential for PasetoCredential<'a> {
Ok(CredentialResponse::Login)
}
Action::Logout => {
- config::save_credentials(self.config, None, &sid)?;
- Ok(CredentialResponse::Logout)
+ if reg_cfg.and_then(|c| c.secret_key).is_some() {
+ config::save_credentials(self.config, None, &sid)?;
+ let reg_name = sid.display_registry_name();
+ let _ = self.config.shell().status(
+ "Logout",
+ format!("secret-key for `{reg_name}` has been removed from local storage"),
+ );
+ Ok(CredentialResponse::Logout)
+ } else {
+ Err(Error::NotFound)
+ }
}
_ => Err(Error::OperationNotSupported),
}
diff --git a/src/tools/cargo/src/cargo/util/credential/process.rs b/src/tools/cargo/src/cargo/util/credential/process.rs
index 89eac1af6..6a6a0a69e 100644
--- a/src/tools/cargo/src/cargo/util/credential/process.rs
+++ b/src/tools/cargo/src/cargo/util/credential/process.rs
@@ -4,12 +4,12 @@
use std::{
io::{BufRead, BufReader, Write},
path::PathBuf,
- process::{Command, Stdio},
+ process::{Child, Command, Stdio},
};
use anyhow::Context;
use cargo_credential::{
- Action, Credential, CredentialHello, CredentialRequest, CredentialResponse, RegistryInfo,
+ Action, Credential, CredentialHello, CredentialRequest, CredentialResponse, Error, RegistryInfo,
};
pub struct CredentialProcessCredential {
@@ -22,31 +22,38 @@ impl<'a> CredentialProcessCredential {
path: PathBuf::from(path),
}
}
-}
-impl<'a> Credential for CredentialProcessCredential {
- fn perform(
+ fn run(
&self,
- registry: &RegistryInfo<'_>,
+ child: &mut Child,
action: &Action<'_>,
+ registry: &RegistryInfo<'_>,
args: &[&str],
- ) -> Result<CredentialResponse, cargo_credential::Error> {
- let mut cmd = Command::new(&self.path);
- cmd.stdout(Stdio::piped());
- cmd.stdin(Stdio::piped());
- cmd.arg("--cargo-plugin");
- tracing::debug!("credential-process: {cmd:?}");
- let mut child = cmd.spawn().context("failed to spawn credential process")?;
+ ) -> Result<Result<CredentialResponse, Error>, Error> {
let mut output_from_child = BufReader::new(child.stdout.take().unwrap());
let mut input_to_child = child.stdin.take().unwrap();
let mut buffer = String::new();
+
+ // Read the CredentialHello
output_from_child
.read_line(&mut buffer)
.context("failed to read hello from credential provider")?;
let credential_hello: CredentialHello =
serde_json::from_str(&buffer).context("failed to deserialize hello")?;
tracing::debug!("credential-process > {credential_hello:?}");
+ if !credential_hello
+ .v
+ .contains(&cargo_credential::PROTOCOL_VERSION_1)
+ {
+ return Err(format!(
+ "credential provider supports protocol versions {:?}, while Cargo supports {:?}",
+ credential_hello.v,
+ [cargo_credential::PROTOCOL_VERSION_1]
+ )
+ .into());
+ }
+ // Send the Credential Request
let req = CredentialRequest {
v: cargo_credential::PROTOCOL_VERSION_1,
action: action.clone(),
@@ -56,14 +63,17 @@ impl<'a> Credential for CredentialProcessCredential {
let request = serde_json::to_string(&req).context("failed to serialize request")?;
tracing::debug!("credential-process < {req:?}");
writeln!(input_to_child, "{request}").context("failed to write to credential provider")?;
-
buffer.clear();
output_from_child
.read_line(&mut buffer)
.context("failed to read response from credential provider")?;
- let response: Result<CredentialResponse, cargo_credential::Error> =
+
+ // Read the Credential Response
+ let response: Result<CredentialResponse, Error> =
serde_json::from_str(&buffer).context("failed to deserialize response")?;
tracing::debug!("credential-process > {response:?}");
+
+ // Tell the credential process we're done by closing stdin. It should exit cleanly.
drop(input_to_child);
let status = child.wait().context("credential process never started")?;
if !status.success() {
@@ -75,6 +85,31 @@ impl<'a> Credential for CredentialProcessCredential {
.into());
}
tracing::trace!("credential process exited successfully");
- response
+ Ok(response)
+ }
+}
+
+impl<'a> Credential for CredentialProcessCredential {
+ fn perform(
+ &self,
+ registry: &RegistryInfo<'_>,
+ action: &Action<'_>,
+ args: &[&str],
+ ) -> Result<CredentialResponse, Error> {
+ let mut cmd = Command::new(&self.path);
+ cmd.stdout(Stdio::piped());
+ cmd.stdin(Stdio::piped());
+ cmd.arg("--cargo-plugin");
+ tracing::debug!("credential-process: {cmd:?}");
+ let mut child = cmd.spawn().context("failed to spawn credential process")?;
+ match self.run(&mut child, action, registry, args) {
+ Err(e) => {
+ // Since running the credential process itself failed, ensure the
+ // process is stopped.
+ let _ = child.kill();
+ Err(e)
+ }
+ Ok(response) => response,
+ }
}
}
diff --git a/src/tools/cargo/src/cargo/util/dependency_queue.rs b/src/tools/cargo/src/cargo/util/dependency_queue.rs
index 33e8bf28e..5650f4b25 100644
--- a/src/tools/cargo/src/cargo/util/dependency_queue.rs
+++ b/src/tools/cargo/src/cargo/util/dependency_queue.rs
@@ -181,9 +181,8 @@ impl<N: Hash + Eq + Clone, E: Eq + Hash + Clone, V> DependencyQueue<N, E, V> {
pub fn finish(&mut self, node: &N, edge: &E) -> Vec<&N> {
// hashset<Node>
let reverse_deps = self.reverse_dep_map.get(node).and_then(|map| map.get(edge));
- let reverse_deps = match reverse_deps {
- Some(deps) => deps,
- None => return Vec::new(),
+ let Some(reverse_deps) = reverse_deps else {
+ return Vec::new();
};
let key = (node.clone(), edge.clone());
let mut result = Vec::new();
diff --git a/src/tools/cargo/src/cargo/util/flock.rs b/src/tools/cargo/src/cargo/util/flock.rs
index 295eb1e14..aa056c965 100644
--- a/src/tools/cargo/src/cargo/util/flock.rs
+++ b/src/tools/cargo/src/cargo/util/flock.rs
@@ -4,11 +4,11 @@ use std::io::{Read, Seek, SeekFrom, Write};
use std::path::{Display, Path, PathBuf};
use crate::util::errors::CargoResult;
+use crate::util::style;
use crate::util::Config;
use anyhow::Context as _;
use cargo_util::paths;
use sys::*;
-use termcolor::Color::Cyan;
#[derive(Debug)]
pub struct FileLock {
@@ -312,7 +312,9 @@ fn acquire(
}
}
let msg = format!("waiting for file lock on {}", msg);
- config.shell().status_with_color("Blocking", &msg, Cyan)?;
+ config
+ .shell()
+ .status_with_color("Blocking", &msg, &style::NOTE)?;
lock_block().with_context(|| format!("failed to lock file: {}", path.display()))?;
return Ok(());
@@ -323,9 +325,8 @@ fn acquire(
use std::mem;
use std::os::unix::prelude::*;
- let path = match CString::new(path.as_os_str().as_bytes()) {
- Ok(path) => path,
- Err(_) => return false,
+ let Ok(path) = CString::new(path.as_os_str().as_bytes()) else {
+ return false;
};
unsafe {
diff --git a/src/tools/cargo/src/cargo/util/graph.rs b/src/tools/cargo/src/cargo/util/graph.rs
index ff4018201..8c4a593ea 100644
--- a/src/tools/cargo/src/cargo/util/graph.rs
+++ b/src/tools/cargo/src/cargo/util/graph.rs
@@ -1,5 +1,5 @@
use std::borrow::Borrow;
-use std::collections::BTreeSet;
+use std::collections::{BTreeMap, BTreeSet, VecDeque};
use std::fmt;
pub struct Graph<N: Clone, E: Clone> {
@@ -87,57 +87,107 @@ impl<N: Eq + Ord + Clone, E: Default + Clone> Graph<N, E> {
false
}
- /// Resolves one of the paths from the given dependent package down to
- /// a leaf.
+ /// Resolves one of the paths from the given dependent package down to a leaf.
+ ///
+ /// The path return will be the shortest path, or more accurately one of the paths with the shortest length.
///
/// Each element contains a node along with an edge except the first one.
/// The representation would look like:
///
/// (Node0,) -> (Node1, Edge01) -> (Node2, Edge12)...
- pub fn path_to_bottom<'a>(&'a self, mut pkg: &'a N) -> Vec<(&'a N, Option<&'a E>)> {
- let mut result = vec![(pkg, None)];
- while let Some(p) = self.nodes.get(pkg).and_then(|p| {
- p.iter()
- // Note that we can have "cycles" introduced through dev-dependency
- // edges, so make sure we don't loop infinitely.
- .find(|&(node, _)| result.iter().all(|p| p.0 != node))
- .map(|(node, edge)| (node, Some(edge)))
- }) {
- result.push(p);
- pkg = p.0;
- }
- result
+ pub fn path_to_bottom<'a>(&'a self, pkg: &'a N) -> Vec<(&'a N, Option<&'a E>)> {
+ self.path_to(pkg, |s, p| s.edges(p))
}
- /// Resolves one of the paths from the given dependent package up to
- /// the root.
+ /// Resolves one of the paths from the given dependent package up to the root.
+ ///
+ /// The path return will be the shortest path, or more accurately one of the paths with the shortest length.
///
/// Each element contains a node along with an edge except the first one.
/// The representation would look like:
///
/// (Node0,) -> (Node1, Edge01) -> (Node2, Edge12)...
- pub fn path_to_top<'a>(&'a self, mut pkg: &'a N) -> Vec<(&'a N, Option<&'a E>)> {
- // Note that this implementation isn't the most robust per se, we'll
- // likely have to tweak this over time. For now though it works for what
- // it's used for!
- let mut result = vec![(pkg, None)];
- let first_pkg_depending_on = |pkg, res: &[(&N, Option<&E>)]| {
- self.nodes
+ pub fn path_to_top<'a>(&'a self, pkg: &'a N) -> Vec<(&'a N, Option<&'a E>)> {
+ self.path_to(pkg, |s, pk| {
+ // Note that this implementation isn't the most robust per se, we'll
+ // likely have to tweak this over time. For now though it works for what
+ // it's used for!
+ s.nodes
.iter()
- .filter(|(_, adjacent)| adjacent.contains_key(pkg))
- // Note that we can have "cycles" introduced through dev-dependency
- // edges, so make sure we don't loop infinitely.
- .find(|&(node, _)| !res.iter().any(|p| p.0 == node))
- .map(|(p, adjacent)| (p, adjacent.get(pkg)))
- };
- while let Some(p) = first_pkg_depending_on(pkg, &result) {
- result.push(p);
- pkg = p.0;
+ .filter_map(|(p, adjacent)| adjacent.get(pk).map(|e| (p, e)))
+ })
+ }
+}
+
+impl<'s, N: Eq + Ord + Clone + 's, E: Default + Clone + 's> Graph<N, E> {
+ fn path_to<'a, F, I>(&'s self, pkg: &'a N, fn_edge: F) -> Vec<(&'a N, Option<&'a E>)>
+ where
+ I: Iterator<Item = (&'a N, &'a E)>,
+ F: Fn(&'s Self, &'a N) -> I,
+ 'a: 's,
+ {
+ let mut back_link = BTreeMap::new();
+ let mut queue = VecDeque::from([pkg]);
+ let mut bottom = None;
+
+ while let Some(p) = queue.pop_front() {
+ bottom = Some(p);
+ for (child, edge) in fn_edge(&self, p) {
+ bottom = None;
+ back_link.entry(child).or_insert_with(|| {
+ queue.push_back(child);
+ (p, edge)
+ });
+ }
+ if bottom.is_some() {
+ break;
+ }
+ }
+
+ let mut result = Vec::new();
+ let mut next =
+ bottom.expect("the only path was a cycle, no dependency graph has this shape");
+ while let Some((p, e)) = back_link.remove(&next) {
+ result.push((next, Some(e)));
+ next = p;
+ }
+ result.push((next, None));
+ result.reverse();
+ #[cfg(debug_assertions)]
+ {
+ for x in result.windows(2) {
+ let [(n2, _), (n1, Some(e12))] = x else {
+ unreachable!()
+ };
+ assert!(std::ptr::eq(
+ self.edge(n1, n2).or(self.edge(n2, n1)).unwrap(),
+ *e12
+ ));
+ }
+ let last = result.last().unwrap().0;
+ // fixme: this may sometimes be wrong when there are cycles.
+ if !fn_edge(&self, last).next().is_none() {
+ self.print_for_test();
+ unreachable!("The last element in the path should not have outgoing edges");
+ }
}
result
}
}
+#[test]
+fn path_to_case() {
+ let mut new = Graph::new();
+ new.link(0, 3);
+ new.link(1, 0);
+ new.link(2, 0);
+ new.link(2, 1);
+ assert_eq!(
+ new.path_to_bottom(&2),
+ vec![(&2, None), (&0, Some(&())), (&3, Some(&()))]
+ );
+}
+
impl<N: Eq + Ord + Clone, E: Default + Clone> Default for Graph<N, E> {
fn default() -> Graph<N, E> {
Graph::new()
@@ -162,6 +212,36 @@ impl<N: fmt::Display + Eq + Ord + Clone, E: Clone> fmt::Debug for Graph<N, E> {
}
}
+impl<N: Eq + Ord + Clone, E: Clone> Graph<N, E> {
+ /// Prints the graph for constructing unit tests.
+ ///
+ /// For purposes of graph traversal algorithms the edge values do not matter,
+ /// and the only value of the node we care about is the order it gets compared in.
+ /// This constructs a graph with the same topology but with integer keys and unit edges.
+ #[cfg(debug_assertions)]
+ #[allow(clippy::print_stderr)]
+ fn print_for_test(&self) {
+ // Isolate and print a test case.
+ let names = self
+ .nodes
+ .keys()
+ .chain(self.nodes.values().flat_map(|vs| vs.keys()))
+ .collect::<BTreeSet<_>>()
+ .into_iter()
+ .collect::<Vec<_>>();
+ let mut new = Graph::new();
+ for n1 in self.nodes.keys() {
+ let name1 = names.binary_search(&n1).unwrap();
+ new.add(name1);
+ for n2 in self.nodes[n1].keys() {
+ let name2 = names.binary_search(&n2).unwrap();
+ *new.link(name1, name2) = ();
+ }
+ }
+ eprintln!("Graph for tests = {new:#?}");
+ }
+}
+
impl<N: Eq + Ord + Clone, E: Eq + Clone> PartialEq for Graph<N, E> {
fn eq(&self, other: &Graph<N, E>) -> bool {
self.nodes.eq(&other.nodes)
diff --git a/src/tools/cargo/src/cargo/util/interning.rs b/src/tools/cargo/src/cargo/util/interning.rs
index 584fdf623..2e3848eaa 100644
--- a/src/tools/cargo/src/cargo/util/interning.rs
+++ b/src/tools/cargo/src/cargo/util/interning.rs
@@ -1,4 +1,5 @@
use serde::{Serialize, Serializer};
+use serde_untagged::UntaggedEnumVisitor;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections::HashSet;
@@ -12,10 +13,6 @@ use std::str;
use std::sync::Mutex;
use std::sync::OnceLock;
-fn leak(s: String) -> &'static str {
- Box::leak(s.into_boxed_str())
-}
-
static STRING_CACHE: OnceLock<Mutex<HashSet<&'static str>>> = OnceLock::new();
#[derive(Clone, Copy)]
@@ -63,12 +60,9 @@ impl Eq for InternedString {}
impl InternedString {
pub fn new(str: &str) -> InternedString {
- let mut cache = STRING_CACHE
- .get_or_init(|| Default::default())
- .lock()
- .unwrap();
+ let mut cache = STRING_CACHE.get_or_init(Default::default).lock().unwrap();
let s = cache.get(str).cloned().unwrap_or_else(|| {
- let s = leak(str.to_string());
+ let s = str.to_string().leak();
cache.insert(s);
s
});
@@ -157,28 +151,14 @@ impl Serialize for InternedString {
}
}
-struct InternedStringVisitor;
-
impl<'de> serde::Deserialize<'de> for InternedString {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
- deserializer.deserialize_str(InternedStringVisitor)
- }
-}
-
-impl<'de> serde::de::Visitor<'de> for InternedStringVisitor {
- type Value = InternedString;
-
- fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- formatter.write_str("an String like thing")
- }
-
- fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
- where
- E: serde::de::Error,
- {
- Ok(InternedString::new(v))
+ UntaggedEnumVisitor::new()
+ .expecting("an String like thing")
+ .string(|value| Ok(InternedString::new(value)))
+ .deserialize(deserializer)
}
}
diff --git a/src/tools/cargo/src/cargo/util/mod.rs b/src/tools/cargo/src/cargo/util/mod.rs
index 26e97e2d2..b4d14f038 100644
--- a/src/tools/cargo/src/cargo/util/mod.rs
+++ b/src/tools/cargo/src/cargo/util/mod.rs
@@ -22,7 +22,7 @@ pub use self::progress::{Progress, ProgressStyle};
pub use self::queue::Queue;
pub use self::restricted_names::validate_package_name;
pub use self::rustc::Rustc;
-pub use self::semver_ext::{OptVersionReq, VersionExt, VersionReqExt};
+pub use self::semver_ext::{OptVersionReq, PartialVersion, RustVersion, VersionExt, VersionReqExt};
pub use self::to_semver::ToSemver;
pub use self::vcs::{existing_vcs_repo, FossilRepo, GitRepo, HgRepo, PijulRepo};
pub use self::workspace::{
@@ -60,12 +60,20 @@ mod queue;
pub mod restricted_names;
pub mod rustc;
mod semver_ext;
+pub mod style;
pub mod to_semver;
pub mod toml;
pub mod toml_mut;
mod vcs;
mod workspace;
+pub fn is_rustup() -> bool {
+ // ALLOWED: `RUSTUP_HOME` should only be read from process env, otherwise
+ // other tools may point to executables from incompatible distributions.
+ #[allow(clippy::disallowed_methods)]
+ std::env::var_os("RUSTUP_HOME").is_some()
+}
+
pub fn elapsed(duration: Duration) -> String {
let secs = duration.as_secs();
@@ -153,7 +161,7 @@ pub fn try_canonicalize<P: AsRef<Path>>(path: P) -> std::io::Result<PathBuf> {
// On Windows `canonicalize` may fail, so we fall back to getting an absolute path.
std::fs::canonicalize(&path).or_else(|_| {
- // Return an error if a file does not exist for better compatiblity with `canonicalize`
+ // Return an error if a file does not exist for better compatibility with `canonicalize`
if !path.as_ref().try_exists()? {
return Err(Error::new(ErrorKind::NotFound, "the path was not found"));
}
@@ -216,7 +224,7 @@ pub fn get_umask() -> u32 {
use std::sync::OnceLock;
static UMASK: OnceLock<libc::mode_t> = OnceLock::new();
// SAFETY: Syscalls are unsafe. Calling `umask` twice is even unsafer for
- // multithreading program, since it doesn't provide a way to retrive the
+ // multithreading program, since it doesn't provide a way to retrieve the
// value without modifications. We use a static `OnceLock` here to ensure
// it only gets call once during the entire program lifetime.
*UMASK.get_or_init(|| unsafe {
diff --git a/src/tools/cargo/src/cargo/util/network/http.rs b/src/tools/cargo/src/cargo/util/network/http.rs
index 73880f60e..869b2fc22 100644
--- a/src/tools/cargo/src/cargo/util/network/http.rs
+++ b/src/tools/cargo/src/cargo/util/network/http.rs
@@ -135,7 +135,7 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<
if let Some(true) = http.debug {
handle.verbose(true)?;
- tracing::debug!("{:#?}", curl::Version::get());
+ tracing::debug!(target: "network", "{:#?}", curl::Version::get());
handle.debug_function(|kind, data| {
enum LogLevel {
Debug,
@@ -167,16 +167,20 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<
line = "set-cookie: [REDACTED]";
}
match level {
- Debug => debug!("http-debug: {prefix} {line}"),
- Trace => trace!("http-debug: {prefix} {line}"),
+ Debug => debug!(target: "network", "http-debug: {prefix} {line}"),
+ Trace => trace!(target: "network", "http-debug: {prefix} {line}"),
}
}
}
Err(_) => {
let len = data.len();
match level {
- Debug => debug!("http-debug: {prefix} ({len} bytes of data)"),
- Trace => trace!("http-debug: {prefix} ({len} bytes of data)"),
+ Debug => {
+ debug!(target: "network", "http-debug: {prefix} ({len} bytes of data)")
+ }
+ Trace => {
+ trace!(target: "network", "http-debug: {prefix} ({len} bytes of data)")
+ }
}
}
}
diff --git a/src/tools/cargo/src/cargo/util/network/mod.rs b/src/tools/cargo/src/cargo/util/network/mod.rs
index 5db594945..2bf781595 100644
--- a/src/tools/cargo/src/cargo/util/network/mod.rs
+++ b/src/tools/cargo/src/cargo/util/network/mod.rs
@@ -29,7 +29,7 @@ macro_rules! try_old_curl {
let result = $e;
if cfg!(target_os = "macos") {
if let Err(e) = result {
- ::tracing::warn!("ignoring libcurl {} error: {}", $msg, e);
+ ::tracing::warn!(target: "network", "ignoring libcurl {} error: {}", $msg, e);
}
} else {
use ::anyhow::Context;
diff --git a/src/tools/cargo/src/cargo/util/network/retry.rs b/src/tools/cargo/src/cargo/util/network/retry.rs
index 5cb7d1e4f..742c2f01c 100644
--- a/src/tools/cargo/src/cargo/util/network/retry.rs
+++ b/src/tools/cargo/src/cargo/util/network/retry.rs
@@ -1,4 +1,45 @@
//! Utilities for retrying a network operation.
+//!
+//! Some network errors are considered "spurious", meaning it is not a real
+//! error (such as a 404 not found) and is likely a transient error (like a
+//! bad network connection) that we can hope will resolve itself shortly. The
+//! [`Retry`] type offers a way to repeatedly perform some kind of network
+//! operation with a delay if it detects one of these possibly transient
+//! errors.
+//!
+//! This supports errors from [`git2`], [`gix`], [`curl`], and
+//! [`HttpNotSuccessful`] 5xx HTTP errors.
+//!
+//! The number of retries can be configured by the user via the `net.retry`
+//! config option. This indicates the number of times to retry the operation
+//! (default 3 times for a total of 4 attempts).
+//!
+//! There are hard-coded constants that indicate how long to sleep between
+//! retries. The constants are tuned to balance a few factors, such as the
+//! responsiveness to the user (we don't want cargo to hang for too long
+//! retrying things), and accommodating things like Cloudfront's default
+//! negative TTL of 10 seconds (if Cloudfront gets a 5xx error for whatever
+//! reason it won't try to fetch again for 10 seconds).
+//!
+//! The timeout also implements a primitive form of random jitter. This is so
+//! that if multiple requests fail at the same time that they don't all flood
+//! the server at the same time when they are retried. This jitter still has
+//! some clumping behavior, but should be good enough.
+//!
+//! [`Retry`] is the core type for implementing retry logic. The
+//! [`Retry::try`] method can be called with a callback, and it will
+//! indicate if it needs to be called again sometime in the future if there
+//! was a possibly transient error. The caller is responsible for sleeping the
+//! appropriate amount of time and then calling [`Retry::try`] again.
+//!
+//! [`with_retry`] is a convenience function that will create a [`Retry`] and
+//! handle repeatedly running a callback until it succeeds, or it runs out of
+//! retries.
+//!
+//! Some interesting resources about retries:
+//! - <https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/>
+//! - <https://en.wikipedia.org/wiki/Exponential_backoff>
+//! - <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After>
use crate::util::errors::HttpNotSuccessful;
use crate::{CargoResult, Config};
@@ -7,15 +48,32 @@ use rand::Rng;
use std::cmp::min;
use std::time::Duration;
+/// State for managing retrying a network operation.
pub struct Retry<'a> {
config: &'a Config,
+ /// The number of failed attempts that have been done so far.
+ ///
+ /// Starts at 0, and increases by one each time an attempt fails.
retries: u64,
+ /// The maximum number of times the operation should be retried.
+ ///
+ /// 0 means it should never retry.
max_retries: u64,
}
+/// The result of attempting some operation via [`Retry::try`].
pub enum RetryResult<T> {
+ /// The operation was successful.
+ ///
+ /// The wrapped value is the return value of the callback function.
Success(T),
+ /// The operation was an error, and it should not be tried again.
Err(anyhow::Error),
+ /// The operation failed, and should be tried again in the future.
+ ///
+ /// The wrapped value is the number of milliseconds to wait before trying
+ /// again. The caller is responsible for waiting this long and then
+ /// calling [`Retry::try`] again.
Retry(u64),
}
@@ -40,7 +98,9 @@ impl<'a> Retry<'a> {
})
}
- /// Returns `Ok(None)` for operations that should be re-tried.
+ /// Calls the given callback, and returns a [`RetryResult`] which
+ /// indicates whether or not this needs to be called again at some point
+ /// in the future to retry the operation if it failed.
pub fn r#try<T>(&mut self, f: impl FnOnce() -> CargoResult<T>) -> RetryResult<T> {
match f() {
Err(ref e) if maybe_spurious(e) && self.retries < self.max_retries => {
diff --git a/src/tools/cargo/src/cargo/util/network/sleep.rs b/src/tools/cargo/src/cargo/util/network/sleep.rs
index fab53263b..d3c770f85 100644
--- a/src/tools/cargo/src/cargo/util/network/sleep.rs
+++ b/src/tools/cargo/src/cargo/util/network/sleep.rs
@@ -68,7 +68,6 @@ impl<T> SleepTracker<T> {
let now = Instant::now();
let mut result = Vec::new();
while let Some(next) = self.heap.peek() {
- tracing::debug!("ERIC: now={now:?} next={:?}", next.wakeup);
if next.wakeup < now {
result.push(self.heap.pop().unwrap().data);
} else {
diff --git a/src/tools/cargo/src/cargo/util/profile.rs b/src/tools/cargo/src/cargo/util/profile.rs
index 29b110492..ede8db191 100644
--- a/src/tools/cargo/src/cargo/util/profile.rs
+++ b/src/tools/cargo/src/cargo/util/profile.rs
@@ -43,9 +43,8 @@ pub fn start<T: fmt::Display>(desc: T) -> Profiler {
impl Drop for Profiler {
fn drop(&mut self) {
- let enabled = match enabled_level() {
- Some(i) => i,
- None => return,
+ let Some(enabled) = enabled_level() else {
+ return;
};
let (start, stack_len) = PROFILE_STACK.with(|stack| {
diff --git a/src/tools/cargo/src/cargo/util/progress.rs b/src/tools/cargo/src/cargo/util/progress.rs
index bcbc1bc0e..374f782bb 100644
--- a/src/tools/cargo/src/cargo/util/progress.rs
+++ b/src/tools/cargo/src/cargo/util/progress.rs
@@ -160,9 +160,8 @@ impl<'cfg> Progress<'cfg> {
/// This may not actually update the display if `tick` is being called too
/// quickly.
pub fn tick(&mut self, cur: usize, max: usize, msg: &str) -> CargoResult<()> {
- let s = match &mut self.state {
- Some(s) => s,
- None => return Ok(()),
+ let Some(s) = &mut self.state else {
+ return Ok(());
};
// Don't update too often as it can cause excessive performance loss
@@ -340,9 +339,8 @@ impl Format {
ProgressStyle::Indeterminate => String::new(),
};
let extra_len = stats.len() + 2 /* [ and ] */ + 15 /* status header */;
- let display_width = match self.width().checked_sub(extra_len) {
- Some(n) => n,
- None => return None,
+ let Some(display_width) = self.width().checked_sub(extra_len) else {
+ return None;
};
let mut string = String::with_capacity(self.max_width);
diff --git a/src/tools/cargo/src/cargo/util/rustc.rs b/src/tools/cargo/src/cargo/util/rustc.rs
index 238145af6..d1bb3981d 100644
--- a/src/tools/cargo/src/cargo/util/rustc.rs
+++ b/src/tools/cargo/src/cargo/util/rustc.rs
@@ -63,8 +63,7 @@ impl Rustc {
let extract = |field: &str| -> CargoResult<&str> {
verbose_version
.lines()
- .find(|l| l.starts_with(field))
- .map(|l| &l[field.len()..])
+ .find_map(|l| l.strip_prefix(field))
.ok_or_else(|| {
anyhow::format_err!(
"`rustc -vV` didn't have a line for `{}`, got:\n{}",
diff --git a/src/tools/cargo/src/cargo/util/semver_ext.rs b/src/tools/cargo/src/cargo/util/semver_ext.rs
index de6d68e16..5839d85d2 100644
--- a/src/tools/cargo/src/cargo/util/semver_ext.rs
+++ b/src/tools/cargo/src/cargo/util/semver_ext.rs
@@ -1,4 +1,5 @@
use semver::{Comparator, Op, Version, VersionReq};
+use serde_untagged::UntaggedEnumVisitor;
use std::fmt::{self, Display};
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
@@ -108,6 +109,218 @@ impl From<VersionReq> for OptVersionReq {
}
}
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug, serde::Serialize)]
+#[serde(transparent)]
+pub struct RustVersion(PartialVersion);
+
+impl std::ops::Deref for RustVersion {
+ type Target = PartialVersion;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl std::str::FromStr for RustVersion {
+ type Err = anyhow::Error;
+
+ fn from_str(value: &str) -> Result<Self, Self::Err> {
+ let partial = value.parse::<PartialVersion>()?;
+ if partial.pre.is_some() {
+ anyhow::bail!("unexpected prerelease field, expected a version like \"1.32\"")
+ }
+ if partial.build.is_some() {
+ anyhow::bail!("unexpected prerelease field, expected a version like \"1.32\"")
+ }
+ Ok(Self(partial))
+ }
+}
+
+impl<'de> serde::Deserialize<'de> for RustVersion {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ UntaggedEnumVisitor::new()
+ .expecting("SemVer version")
+ .string(|value| value.parse().map_err(serde::de::Error::custom))
+ .deserialize(deserializer)
+ }
+}
+
+impl Display for RustVersion {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug)]
+pub struct PartialVersion {
+ pub major: u64,
+ pub minor: Option<u64>,
+ pub patch: Option<u64>,
+ pub pre: Option<semver::Prerelease>,
+ pub build: Option<semver::BuildMetadata>,
+}
+
+impl PartialVersion {
+ pub fn version(&self) -> Option<Version> {
+ Some(Version {
+ major: self.major,
+ minor: self.minor?,
+ patch: self.patch?,
+ pre: self.pre.clone().unwrap_or_default(),
+ build: self.build.clone().unwrap_or_default(),
+ })
+ }
+
+ pub fn caret_req(&self) -> VersionReq {
+ VersionReq {
+ comparators: vec![Comparator {
+ op: semver::Op::Caret,
+ major: self.major,
+ minor: self.minor,
+ patch: self.patch,
+ pre: self.pre.as_ref().cloned().unwrap_or_default(),
+ }],
+ }
+ }
+
+ /// Check if this matches a version, including build metadata
+ ///
+ /// Build metadata does not affect version precedence but may be necessary for uniquely
+ /// identifying a package.
+ pub fn matches(&self, version: &Version) -> bool {
+ if !version.pre.is_empty() && self.pre.is_none() {
+ // Pre-release versions must be explicitly opted into, if for no other reason than to
+ // give us room to figure out and define the semantics
+ return false;
+ }
+ self.major == version.major
+ && self.minor.map(|f| f == version.minor).unwrap_or(true)
+ && self.patch.map(|f| f == version.patch).unwrap_or(true)
+ && self.pre.as_ref().map(|f| f == &version.pre).unwrap_or(true)
+ && self
+ .build
+ .as_ref()
+ .map(|f| f == &version.build)
+ .unwrap_or(true)
+ }
+}
+
+impl From<semver::Version> for PartialVersion {
+ fn from(ver: semver::Version) -> Self {
+ let pre = if ver.pre.is_empty() {
+ None
+ } else {
+ Some(ver.pre)
+ };
+ let build = if ver.build.is_empty() {
+ None
+ } else {
+ Some(ver.build)
+ };
+ Self {
+ major: ver.major,
+ minor: Some(ver.minor),
+ patch: Some(ver.patch),
+ pre,
+ build,
+ }
+ }
+}
+
+impl std::str::FromStr for PartialVersion {
+ type Err = anyhow::Error;
+
+ fn from_str(value: &str) -> Result<Self, Self::Err> {
+ if is_req(value) {
+ anyhow::bail!("unexpected version requirement, expected a version like \"1.32\"")
+ }
+ match semver::Version::parse(value) {
+ Ok(ver) => Ok(ver.into()),
+ Err(_) => {
+ // HACK: Leverage `VersionReq` for partial version parsing
+ let mut version_req = match semver::VersionReq::parse(value) {
+ Ok(req) => req,
+ Err(_) if value.contains('-') => {
+ anyhow::bail!(
+ "unexpected prerelease field, expected a version like \"1.32\""
+ )
+ }
+ Err(_) if value.contains('+') => {
+ anyhow::bail!("unexpected build field, expected a version like \"1.32\"")
+ }
+ Err(_) => anyhow::bail!("expected a version like \"1.32\""),
+ };
+ assert_eq!(version_req.comparators.len(), 1, "guaranteed by is_req");
+ let comp = version_req.comparators.pop().unwrap();
+ assert_eq!(comp.op, semver::Op::Caret, "guaranteed by is_req");
+ let pre = if comp.pre.is_empty() {
+ None
+ } else {
+ Some(comp.pre)
+ };
+ Ok(Self {
+ major: comp.major,
+ minor: comp.minor,
+ patch: comp.patch,
+ pre,
+ build: None,
+ })
+ }
+ }
+ }
+}
+
+impl Display for PartialVersion {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let major = self.major;
+ write!(f, "{major}")?;
+ if let Some(minor) = self.minor {
+ write!(f, ".{minor}")?;
+ }
+ if let Some(patch) = self.patch {
+ write!(f, ".{patch}")?;
+ }
+ if let Some(pre) = self.pre.as_ref() {
+ write!(f, "-{pre}")?;
+ }
+ if let Some(build) = self.build.as_ref() {
+ write!(f, "+{build}")?;
+ }
+ Ok(())
+ }
+}
+
+impl serde::Serialize for PartialVersion {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ serializer.collect_str(self)
+ }
+}
+
+impl<'de> serde::Deserialize<'de> for PartialVersion {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ UntaggedEnumVisitor::new()
+ .expecting("SemVer version")
+ .string(|value| value.parse().map_err(serde::de::Error::custom))
+ .deserialize(deserializer)
+ }
+}
+
+fn is_req(value: &str) -> bool {
+ let Some(first) = value.chars().next() else {
+ return false;
+ };
+ "<>=^~".contains(first) || value.contains('*') || value.contains(',')
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src/tools/cargo/src/cargo/util/style.rs b/src/tools/cargo/src/cargo/util/style.rs
new file mode 100644
index 000000000..618a10876
--- /dev/null
+++ b/src/tools/cargo/src/cargo/util/style.rs
@@ -0,0 +1,13 @@
+use anstyle::*;
+
+pub const NOP: Style = Style::new();
+pub const HEADER: Style = AnsiColor::Green.on_default().effects(Effects::BOLD);
+pub const USAGE: Style = AnsiColor::Green.on_default().effects(Effects::BOLD);
+pub const LITERAL: Style = AnsiColor::Cyan.on_default().effects(Effects::BOLD);
+pub const PLACEHOLDER: Style = AnsiColor::Cyan.on_default();
+pub const ERROR: Style = AnsiColor::Red.on_default().effects(Effects::BOLD);
+pub const WARN: Style = AnsiColor::Yellow.on_default().effects(Effects::BOLD);
+pub const NOTE: Style = AnsiColor::Cyan.on_default().effects(Effects::BOLD);
+pub const GOOD: Style = AnsiColor::Green.on_default().effects(Effects::BOLD);
+pub const VALID: Style = AnsiColor::Cyan.on_default().effects(Effects::BOLD);
+pub const INVALID: Style = AnsiColor::Yellow.on_default().effects(Effects::BOLD);
diff --git a/src/tools/cargo/src/cargo/util/to_semver.rs b/src/tools/cargo/src/cargo/util/to_semver.rs
index 25da9dfb9..3cc9e5706 100644
--- a/src/tools/cargo/src/cargo/util/to_semver.rs
+++ b/src/tools/cargo/src/cargo/util/to_semver.rs
@@ -15,7 +15,10 @@ impl<'a> ToSemver for &'a str {
fn to_semver(self) -> CargoResult<Version> {
match Version::parse(self.trim()) {
Ok(v) => Ok(v),
- Err(..) => Err(anyhow::format_err!("cannot parse '{}' as a semver", self)),
+ Err(..) => Err(anyhow::format_err!(
+ "cannot parse '{}' as a SemVer version",
+ self
+ )),
}
}
}
diff --git a/src/tools/cargo/src/cargo/util/toml/embedded.rs b/src/tools/cargo/src/cargo/util/toml/embedded.rs
index 395430c1b..482268923 100644
--- a/src/tools/cargo/src/cargo/util/toml/embedded.rs
+++ b/src/tools/cargo/src/cargo/util/toml/embedded.rs
@@ -15,26 +15,72 @@ pub fn expand_manifest(
path: &std::path::Path,
config: &Config,
) -> CargoResult<String> {
- let comment = match extract_comment(content) {
- Ok(comment) => Some(comment),
- Err(err) => {
- tracing::trace!("failed to extract doc comment: {err}");
- None
+ let source = split_source(content)?;
+ if let Some(frontmatter) = source.frontmatter {
+ match source.info {
+ Some("cargo") => {}
+ None => {
+ anyhow::bail!("frontmatter is missing an infostring; specify `cargo` for embedding a manifest");
+ }
+ Some(other) => {
+ if let Some(remainder) = other.strip_prefix("cargo,") {
+ anyhow::bail!("cargo does not support frontmatter infostring attributes like `{remainder}` at this time")
+ } else {
+ anyhow::bail!("frontmatter infostring `{other}` is unsupported by cargo; specify `cargo` for embedding a manifest")
+ }
+ }
}
- }
- .unwrap_or_default();
- let manifest = match extract_manifest(&comment)? {
- Some(manifest) => Some(manifest),
- None => {
- tracing::trace!("failed to extract manifest");
- None
+
+ // HACK: until rustc has native support for this syntax, we have to remove it from the
+ // source file
+ use std::fmt::Write as _;
+ let hash = crate::util::hex::short_hash(&path.to_string_lossy());
+ let mut rel_path = std::path::PathBuf::new();
+ rel_path.push("target");
+ rel_path.push(&hash[0..2]);
+ rel_path.push(&hash[2..]);
+ let target_dir = config.home().join(rel_path);
+ let hacked_path = target_dir
+ .join(
+ path.file_name()
+ .expect("always a name for embedded manifests"),
+ )
+ .into_path_unlocked();
+ let mut hacked_source = String::new();
+ if let Some(shebang) = source.shebang {
+ writeln!(hacked_source, "{shebang}")?;
+ }
+ writeln!(hacked_source)?; // open
+ for _ in 0..frontmatter.lines().count() {
+ writeln!(hacked_source)?;
}
+ writeln!(hacked_source)?; // close
+ writeln!(hacked_source, "{}", source.content)?;
+ if let Some(parent) = hacked_path.parent() {
+ cargo_util::paths::create_dir_all(parent)?;
+ }
+ cargo_util::paths::write_if_changed(&hacked_path, hacked_source)?;
+
+ let manifest = expand_manifest_(&frontmatter, &hacked_path, config)
+ .with_context(|| format!("failed to parse manifest at {}", path.display()))?;
+ let manifest = toml::to_string_pretty(&manifest)?;
+ Ok(manifest)
+ } else {
+ // Legacy doc-comment support; here only for transitional purposes
+ let comment = extract_comment(content)?.unwrap_or_default();
+ let manifest = match extract_manifest(&comment)? {
+ Some(manifest) => Some(manifest),
+ None => {
+ tracing::trace!("failed to extract manifest");
+ None
+ }
+ }
+ .unwrap_or_default();
+ let manifest = expand_manifest_(&manifest, path, config)
+ .with_context(|| format!("failed to parse manifest at {}", path.display()))?;
+ let manifest = toml::to_string_pretty(&manifest)?;
+ Ok(manifest)
}
- .unwrap_or_default();
- let manifest = expand_manifest_(&manifest, path, config)
- .with_context(|| format!("failed to parse manifest at {}", path.display()))?;
- let manifest = toml::to_string_pretty(&manifest)?;
- Ok(manifest)
}
fn expand_manifest_(
@@ -66,10 +112,8 @@ fn expand_manifest_(
anyhow::bail!("`package.{key}` is not allowed in embedded manifests")
}
}
- let file_name = path
- .file_name()
- .ok_or_else(|| anyhow::format_err!("no file name"))?
- .to_string_lossy();
+ // HACK: Using an absolute path while `hacked_path` is in use
+ let bin_path = path.to_string_lossy().into_owned();
let file_stem = path
.file_stem()
.ok_or_else(|| anyhow::format_err!("no file name"))?
@@ -103,10 +147,7 @@ fn expand_manifest_(
let mut bin = toml::Table::new();
bin.insert("name".to_owned(), toml::Value::String(bin_name));
- bin.insert(
- "path".to_owned(),
- toml::Value::String(file_name.into_owned()),
- );
+ bin.insert("path".to_owned(), toml::Value::String(bin_path));
manifest.insert(
"bin".to_owned(),
toml::Value::Array(vec![toml::Value::Table(bin)]),
@@ -159,8 +200,82 @@ fn sanitize_name(name: &str) -> String {
name
}
+struct Source<'s> {
+ shebang: Option<&'s str>,
+ info: Option<&'s str>,
+ frontmatter: Option<&'s str>,
+ content: &'s str,
+}
+
+fn split_source(input: &str) -> CargoResult<Source<'_>> {
+ let mut source = Source {
+ shebang: None,
+ info: None,
+ frontmatter: None,
+ content: input,
+ };
+
+ // See rust-lang/rust's compiler/rustc_lexer/src/lib.rs's `strip_shebang`
+ // Shebang must start with `#!` literally, without any preceding whitespace.
+ // For simplicity we consider any line starting with `#!` a shebang,
+ // regardless of restrictions put on shebangs by specific platforms.
+ if let Some(rest) = source.content.strip_prefix("#!") {
+ // Ok, this is a shebang but if the next non-whitespace token is `[`,
+ // then it may be valid Rust code, so consider it Rust code.
+ if rest.trim_start().starts_with('[') {
+ return Ok(source);
+ }
+
+ // No other choice than to consider this a shebang.
+ let (shebang, content) = source
+ .content
+ .split_once('\n')
+ .unwrap_or((source.content, ""));
+ source.shebang = Some(shebang);
+ source.content = content;
+ }
+
+ let tick_end = source
+ .content
+ .char_indices()
+ .find_map(|(i, c)| (c != '`').then_some(i))
+ .unwrap_or(source.content.len());
+ let (fence_pattern, rest) = match tick_end {
+ 0 => {
+ return Ok(source);
+ }
+ 1 | 2 => {
+ anyhow::bail!("found {tick_end} backticks in rust frontmatter, expected at least 3")
+ }
+ _ => source.content.split_at(tick_end),
+ };
+ let (info, content) = rest.split_once("\n").unwrap_or((rest, ""));
+ if !info.is_empty() {
+ source.info = Some(info.trim_end());
+ }
+ source.content = content;
+
+ let Some((frontmatter, content)) = source.content.split_once(fence_pattern) else {
+ anyhow::bail!("no closing `{fence_pattern}` found for frontmatter");
+ };
+ source.frontmatter = Some(frontmatter);
+ source.content = content;
+
+ let (line, content) = source
+ .content
+ .split_once("\n")
+ .unwrap_or((source.content, ""));
+ let line = line.trim();
+ if !line.is_empty() {
+ anyhow::bail!("unexpected trailing content on closing fence: `{line}`");
+ }
+ source.content = content;
+
+ Ok(source)
+}
+
/// Locates a "code block manifest" in Rust source.
-fn extract_comment(input: &str) -> CargoResult<String> {
+fn extract_comment(input: &str) -> CargoResult<Option<String>> {
let mut doc_fragments = Vec::new();
let file = syn::parse_file(input)?;
// HACK: `syn` doesn't tell us what kind of comment was used, so infer it from how many
@@ -181,7 +296,7 @@ fn extract_comment(input: &str) -> CargoResult<String> {
}
}
if doc_fragments.is_empty() {
- anyhow::bail!("no doc-comment found");
+ return Ok(None);
}
unindent_doc_fragments(&mut doc_fragments);
@@ -190,7 +305,7 @@ fn extract_comment(input: &str) -> CargoResult<String> {
add_doc_fragment(&mut doc_comment, frag);
}
- Ok(doc_comment)
+ Ok(Some(doc_comment))
}
/// A `#[doc]`
@@ -496,7 +611,7 @@ mod test_expand {
snapbox::assert_eq(
r#"[[bin]]
name = "test-"
-path = "test.rs"
+path = "/home/me/test.rs"
[package]
autobenches = false
@@ -523,7 +638,7 @@ strip = true
snapbox::assert_eq(
r#"[[bin]]
name = "test-"
-path = "test.rs"
+path = "/home/me/test.rs"
[dependencies]
time = "0.1.25"
@@ -561,29 +676,30 @@ mod test_comment {
macro_rules! ec {
($s:expr) => {
- extract_comment($s).unwrap_or_else(|err| panic!("{}", err))
+ extract_comment($s)
+ .unwrap_or_else(|err| panic!("{}", err))
+ .unwrap()
};
}
#[test]
fn test_no_comment() {
- snapbox::assert_eq(
- "no doc-comment found",
+ assert_eq!(
+ None,
extract_comment(
r#"
fn main () {
}
"#,
)
- .unwrap_err()
- .to_string(),
+ .unwrap()
);
}
#[test]
fn test_no_comment_she_bang() {
- snapbox::assert_eq(
- "no doc-comment found",
+ assert_eq!(
+ None,
extract_comment(
r#"#!/usr/bin/env cargo-eval
@@ -591,8 +707,7 @@ fn main () {
}
"#,
)
- .unwrap_err()
- .to_string(),
+ .unwrap()
);
}
diff --git a/src/tools/cargo/src/cargo/util/toml/mod.rs b/src/tools/cargo/src/cargo/util/toml/mod.rs
index 963c4afaa..2e730b4e9 100644
--- a/src/tools/cargo/src/cargo/util/toml/mod.rs
+++ b/src/tools/cargo/src/cargo/util/toml/mod.rs
@@ -1,7 +1,6 @@
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::ffi::OsStr;
use std::fmt::{self, Display, Write};
-use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::str::{self, FromStr};
@@ -11,11 +10,10 @@ use cargo_platform::Platform;
use cargo_util::paths;
use itertools::Itertools;
use lazycell::LazyCell;
-use semver::{self, VersionReq};
-use serde::de::IntoDeserializer as _;
-use serde::de::{self, Unexpected};
+use serde::de::{self, IntoDeserializer as _, Unexpected};
use serde::ser;
use serde::{Deserialize, Serialize};
+use serde_untagged::UntaggedEnumVisitor;
use tracing::{debug, trace};
use url::Url;
@@ -31,7 +29,8 @@ use crate::sources::{CRATES_IO_INDEX, CRATES_IO_REGISTRY};
use crate::util::errors::{CargoResult, ManifestError};
use crate::util::interning::InternedString;
use crate::util::{
- self, config::ConfigRelativePath, validate_package_name, Config, IntoUrl, VersionReqExt,
+ self, config::ConfigRelativePath, validate_package_name, Config, IntoUrl, OptVersionReq,
+ RustVersion,
};
pub mod embedded;
@@ -99,26 +98,9 @@ fn read_manifest_from_str(
) -> CargoResult<(EitherManifest, Vec<PathBuf>)> {
let package_root = manifest_file.parent().unwrap();
- let toml = {
- let pretty_filename = manifest_file
- .strip_prefix(config.cwd())
- .unwrap_or(manifest_file);
- parse_document(contents, pretty_filename, config)?
- };
-
- // Provide a helpful error message for a common user error.
- if let Some(package) = toml.get("package").or_else(|| toml.get("project")) {
- if let Some(feats) = package.get("cargo-features") {
- bail!(
- "cargo-features = {} was found in the wrong location: it \
- should be set at the top of Cargo.toml before any tables",
- feats
- );
- }
- }
-
let mut unused = BTreeSet::new();
- let manifest: TomlManifest = serde_ignored::deserialize(toml.into_deserializer(), |path| {
+ let deserializer = toml::de::Deserializer::new(contents);
+ let manifest: TomlManifest = serde_ignored::deserialize(deserializer, |path| {
let mut key = String::new();
stringify(&mut key, &path);
unused.insert(key);
@@ -194,8 +176,7 @@ fn read_manifest_from_str(
pub fn parse_document(toml: &str, _file: &Path, _config: &Config) -> CargoResult<toml::Table> {
// At the moment, no compatibility checks are needed.
- toml.parse()
- .map_err(|e| anyhow::Error::from(e).context("could not parse input as TOML"))
+ toml.parse().map_err(Into::into)
}
/// Warn about paths that have been deprecated and may conflict.
@@ -230,34 +211,14 @@ impl<'de, P: Deserialize<'de> + Clone> de::Deserialize<'de> for TomlDependency<P
where
D: de::Deserializer<'de>,
{
- struct TomlDependencyVisitor<P>(PhantomData<P>);
-
- impl<'de, P: Deserialize<'de> + Clone> de::Visitor<'de> for TomlDependencyVisitor<P> {
- type Value = TomlDependency<P>;
-
- fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- formatter.write_str(
- "a version string like \"0.9.8\" or a \
+ UntaggedEnumVisitor::new()
+ .expecting(
+ "a version string like \"0.9.8\" or a \
detailed dependency like { version = \"0.9.8\" }",
- )
- }
-
- fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
- where
- E: de::Error,
- {
- Ok(TomlDependency::Simple(s.to_owned()))
- }
-
- fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>
- where
- V: de::MapAccess<'de>,
- {
- let mvd = de::value::MapAccessDeserializer::new(map);
- DetailedTomlDependency::deserialize(mvd).map(TomlDependency::Detailed)
- }
- }
- deserializer.deserialize_any(TomlDependencyVisitor(PhantomData))
+ )
+ .string(|value| Ok(TomlDependency::Simple(value.to_owned())))
+ .map(|value| value.deserialize().map(TomlDependency::Detailed))
+ .deserialize(deserializer)
}
}
@@ -377,7 +338,7 @@ pub struct TomlManifest {
patch: Option<BTreeMap<String, BTreeMap<String, TomlDependency>>>,
workspace: Option<TomlWorkspace>,
badges: Option<MaybeWorkspaceBtreeMap>,
- lints: Option<toml::Value>,
+ lints: Option<MaybeWorkspaceLints>,
}
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
@@ -417,39 +378,22 @@ impl<'de> de::Deserialize<'de> for TomlOptLevel {
where
D: de::Deserializer<'de>,
{
- struct Visitor;
-
- impl<'de> de::Visitor<'de> for Visitor {
- type Value = TomlOptLevel;
-
- fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- formatter.write_str("an optimization level")
- }
-
- fn visit_i64<E>(self, value: i64) -> Result<TomlOptLevel, E>
- where
- E: de::Error,
- {
- Ok(TomlOptLevel(value.to_string()))
- }
-
- fn visit_str<E>(self, value: &str) -> Result<TomlOptLevel, E>
- where
- E: de::Error,
- {
+ use serde::de::Error as _;
+ UntaggedEnumVisitor::new()
+ .expecting("an optimization level")
+ .i64(|value| Ok(TomlOptLevel(value.to_string())))
+ .string(|value| {
if value == "s" || value == "z" {
Ok(TomlOptLevel(value.to_string()))
} else {
- Err(E::custom(format!(
+ Err(serde_untagged::de::Error::custom(format!(
"must be `0`, `1`, `2`, `3`, `s` or `z`, \
but found the string: \"{}\"",
value
)))
}
- }
- }
-
- d.deserialize_any(Visitor)
+ })
+ .deserialize(d)
}
}
@@ -494,58 +438,48 @@ impl<'de> de::Deserialize<'de> for TomlDebugInfo {
where
D: de::Deserializer<'de>,
{
- struct Visitor;
-
- impl<'de> de::Visitor<'de> for Visitor {
- type Value = TomlDebugInfo;
-
- fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- formatter.write_str(
- "a boolean, 0, 1, 2, \"line-tables-only\", or \"line-directives-only\"",
- )
- }
-
- fn visit_i64<E>(self, value: i64) -> Result<TomlDebugInfo, E>
- where
- E: de::Error,
- {
+ use serde::de::Error as _;
+ let expecting = "a boolean, 0, 1, 2, \"line-tables-only\", or \"line-directives-only\"";
+ UntaggedEnumVisitor::new()
+ .expecting(expecting)
+ .bool(|value| {
+ Ok(if value {
+ TomlDebugInfo::Full
+ } else {
+ TomlDebugInfo::None
+ })
+ })
+ .i64(|value| {
let debuginfo = match value {
0 => TomlDebugInfo::None,
1 => TomlDebugInfo::Limited,
2 => TomlDebugInfo::Full,
- _ => return Err(de::Error::invalid_value(Unexpected::Signed(value), &self)),
+ _ => {
+ return Err(serde_untagged::de::Error::invalid_value(
+ Unexpected::Signed(value),
+ &expecting,
+ ))
+ }
};
Ok(debuginfo)
- }
-
- fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
- where
- E: de::Error,
- {
- Ok(if v {
- TomlDebugInfo::Full
- } else {
- TomlDebugInfo::None
- })
- }
-
- fn visit_str<E>(self, value: &str) -> Result<TomlDebugInfo, E>
- where
- E: de::Error,
- {
+ })
+ .string(|value| {
let debuginfo = match value {
"none" => TomlDebugInfo::None,
"limited" => TomlDebugInfo::Limited,
"full" => TomlDebugInfo::Full,
"line-directives-only" => TomlDebugInfo::LineDirectivesOnly,
"line-tables-only" => TomlDebugInfo::LineTablesOnly,
- _ => return Err(de::Error::invalid_value(Unexpected::Str(value), &self)),
+ _ => {
+ return Err(serde_untagged::de::Error::invalid_value(
+ Unexpected::Str(value),
+ &expecting,
+ ))
+ }
};
Ok(debuginfo)
- }
- }
-
- d.deserialize_any(Visitor)
+ })
+ .deserialize(d)
}
}
@@ -865,8 +799,8 @@ impl TomlProfile {
self.codegen_units = Some(v);
}
- if let Some(v) = &profile.debug {
- self.debug = Some(v.clone());
+ if let Some(v) = profile.debug {
+ self.debug = Some(v);
}
if let Some(v) = profile.debug_assertions {
@@ -944,32 +878,11 @@ impl<'de> de::Deserialize<'de> for StringOrVec {
where
D: de::Deserializer<'de>,
{
- struct Visitor;
-
- impl<'de> de::Visitor<'de> for Visitor {
- type Value = StringOrVec;
-
- fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- formatter.write_str("string or list of strings")
- }
-
- fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
- where
- E: de::Error,
- {
- Ok(StringOrVec(vec![s.to_string()]))
- }
-
- fn visit_seq<V>(self, v: V) -> Result<Self::Value, V::Error>
- where
- V: de::SeqAccess<'de>,
- {
- let seq = de::value::SeqAccessDeserializer::new(v);
- Vec::deserialize(seq).map(StringOrVec)
- }
- }
-
- deserializer.deserialize_any(Visitor)
+ UntaggedEnumVisitor::new()
+ .expecting("string or list of strings")
+ .string(|value| Ok(StringOrVec(vec![value.to_owned()])))
+ .seq(|value| value.deserialize().map(StringOrVec))
+ .deserialize(deserializer)
}
}
@@ -979,13 +892,25 @@ impl StringOrVec {
}
}
-#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
-#[serde(untagged, expecting = "expected a boolean or a string")]
+#[derive(Clone, Debug, Serialize, Eq, PartialEq)]
+#[serde(untagged)]
pub enum StringOrBool {
String(String),
Bool(bool),
}
+impl<'de> Deserialize<'de> for StringOrBool {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ UntaggedEnumVisitor::new()
+ .bool(|b| Ok(StringOrBool::Bool(b)))
+ .string(|s| Ok(StringOrBool::String(s.to_owned())))
+ .deserialize(deserializer)
+ }
+}
+
#[derive(PartialEq, Clone, Debug, Serialize)]
#[serde(untagged)]
pub enum VecStringOrBool {
@@ -998,32 +923,11 @@ impl<'de> de::Deserialize<'de> for VecStringOrBool {
where
D: de::Deserializer<'de>,
{
- struct Visitor;
-
- impl<'de> de::Visitor<'de> for Visitor {
- type Value = VecStringOrBool;
-
- fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- formatter.write_str("a boolean or vector of strings")
- }
-
- fn visit_seq<V>(self, v: V) -> Result<Self::Value, V::Error>
- where
- V: de::SeqAccess<'de>,
- {
- let seq = de::value::SeqAccessDeserializer::new(v);
- Vec::deserialize(seq).map(VecStringOrBool::VecString)
- }
-
- fn visit_bool<E>(self, b: bool) -> Result<Self::Value, E>
- where
- E: de::Error,
- {
- Ok(VecStringOrBool::Bool(b))
- }
- }
-
- deserializer.deserialize_any(Visitor)
+ UntaggedEnumVisitor::new()
+ .expecting("a boolean or vector of strings")
+ .bool(|value| Ok(VecStringOrBool::Bool(value)))
+ .seq(|value| value.deserialize().map(VecStringOrBool::VecString))
+ .deserialize(deserializer)
}
}
@@ -1031,35 +935,16 @@ fn version_trim_whitespace<'de, D>(deserializer: D) -> Result<MaybeWorkspaceSemv
where
D: de::Deserializer<'de>,
{
- struct Visitor;
-
- impl<'de> de::Visitor<'de> for Visitor {
- type Value = MaybeWorkspaceSemverVersion;
-
- fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
- formatter.write_str("SemVer version")
- }
-
- fn visit_str<E>(self, string: &str) -> Result<Self::Value, E>
- where
- E: de::Error,
- {
- match string.trim().parse().map_err(de::Error::custom) {
+ UntaggedEnumVisitor::new()
+ .expecting("SemVer version")
+ .string(
+ |value| match value.trim().parse().map_err(de::Error::custom) {
Ok(parsed) => Ok(MaybeWorkspace::Defined(parsed)),
Err(e) => Err(e),
- }
- }
-
- fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>
- where
- V: de::MapAccess<'de>,
- {
- let mvd = de::value::MapAccessDeserializer::new(map);
- TomlWorkspaceField::deserialize(mvd).map(MaybeWorkspace::Workspace)
- }
- }
-
- deserializer.deserialize_any(Visitor)
+ },
+ )
+ .map(|value| value.deserialize().map(MaybeWorkspace::Workspace))
+ .deserialize(deserializer)
}
/// This Trait exists to make [`MaybeWorkspace::Workspace`] generic. It makes deserialization of
@@ -1078,7 +963,7 @@ pub trait WorkspaceInherit {
}
/// An enum that allows for inheriting keys from a workspace in a Cargo.toml.
-#[derive(Serialize, Clone, Debug)]
+#[derive(Serialize, Copy, Clone, Debug)]
#[serde(untagged)]
pub enum MaybeWorkspace<T, W: WorkspaceInherit> {
/// The "defined" type, or the type that that is used when not inheriting from a workspace.
@@ -1297,6 +1182,42 @@ impl<'de> de::Deserialize<'de> for MaybeWorkspaceString {
}
}
+type MaybeWorkspaceRustVersion = MaybeWorkspace<RustVersion, TomlWorkspaceField>;
+impl<'de> de::Deserialize<'de> for MaybeWorkspaceRustVersion {
+ fn deserialize<D>(d: D) -> Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ struct Visitor;
+
+ impl<'de> de::Visitor<'de> for Visitor {
+ type Value = MaybeWorkspaceRustVersion;
+
+ fn expecting(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ f.write_str("a semver or workspace")
+ }
+
+ fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ let value = value.parse::<RustVersion>().map_err(|e| E::custom(e))?;
+ Ok(MaybeWorkspaceRustVersion::Defined(value))
+ }
+
+ fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>
+ where
+ V: de::MapAccess<'de>,
+ {
+ let mvd = de::value::MapAccessDeserializer::new(map);
+ TomlWorkspaceField::deserialize(mvd).map(MaybeWorkspace::Workspace)
+ }
+ }
+
+ d.deserialize_any(Visitor)
+ }
+}
+
type MaybeWorkspaceVecString = MaybeWorkspace<Vec<String>, TomlWorkspaceField>;
impl<'de> de::Deserialize<'de> for MaybeWorkspaceVecString {
fn deserialize<D>(d: D) -> Result<Self, D::Error>
@@ -1444,30 +1365,7 @@ impl<'de> de::Deserialize<'de> for MaybeWorkspaceBtreeMap {
}
}
-type MaybeWorkspaceLints = MaybeWorkspace<TomlLints, TomlWorkspaceField>;
-
-impl<'de> de::Deserialize<'de> for MaybeWorkspaceLints {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: de::Deserializer<'de>,
- {
- let value = serde_value::Value::deserialize(deserializer)?;
-
- if let Ok(w) = TomlWorkspaceField::deserialize(
- serde_value::ValueDeserializer::<D::Error>::new(value.clone()),
- ) {
- return if w.workspace() {
- Ok(MaybeWorkspace::Workspace(w))
- } else {
- Err(de::Error::custom("`workspace` cannot be false"))
- };
- }
- TomlLints::deserialize(serde_value::ValueDeserializer::<D::Error>::new(value))
- .map(MaybeWorkspace::Defined)
- }
-}
-
-#[derive(Deserialize, Serialize, Clone, Debug)]
+#[derive(Deserialize, Serialize, Copy, Clone, Debug)]
pub struct TomlWorkspaceField {
#[serde(deserialize_with = "bool_no_false")]
workspace: bool,
@@ -1502,16 +1400,14 @@ impl WorkspaceInherit for TomlWorkspaceField {
#[serde(rename_all = "kebab-case")]
pub struct TomlPackage {
edition: Option<MaybeWorkspaceString>,
- rust_version: Option<MaybeWorkspaceString>,
+ rust_version: Option<MaybeWorkspaceRustVersion>,
name: InternedString,
#[serde(deserialize_with = "version_trim_whitespace")]
version: MaybeWorkspaceSemverVersion,
authors: Option<MaybeWorkspaceVecString>,
build: Option<StringOrBool>,
metabuild: Option<StringOrVec>,
- #[serde(rename = "default-target")]
default_target: Option<String>,
- #[serde(rename = "forced-target")]
forced_target: Option<String>,
links: Option<String>,
exclude: Option<MaybeWorkspaceVecString>,
@@ -1537,6 +1433,10 @@ pub struct TomlPackage {
repository: Option<MaybeWorkspaceString>,
resolver: Option<String>,
+ // Provide a helpful error message for a common user error.
+ #[serde(rename = "cargo-features", skip_serializing)]
+ _invalid_cargo_features: Option<InvalidCargoFeatures>,
+
// Note that this field must come last due to the way toml serialization
// works which requires tables to be emitted after all values.
metadata: Option<toml::Value>,
@@ -1553,7 +1453,7 @@ pub struct TomlWorkspace {
// Properties that can be inherited by members.
package: Option<InheritableFields>,
dependencies: Option<BTreeMap<String, TomlDependency>>,
- lints: Option<toml::Value>,
+ lints: Option<TomlLints>,
// Note that this field must come last due to the way toml serialization
// works which requires tables to be emitted after all values.
@@ -1588,7 +1488,7 @@ pub struct InheritableFields {
exclude: Option<Vec<String>>,
include: Option<Vec<String>>,
#[serde(rename = "rust-version")]
- rust_version: Option<String>,
+ rust_version: Option<RustVersion>,
// We use skip here since it will never be present when deserializing
// and we don't want it present when serializing
#[serde(skip)]
@@ -1628,7 +1528,7 @@ impl InheritableFields {
("package.license", license -> String),
("package.publish", publish -> VecStringOrBool),
("package.repository", repository -> String),
- ("package.rust-version", rust_version -> String),
+ ("package.rust-version", rust_version -> RustVersion),
("package.version", version -> semver::Version),
}
@@ -1857,10 +1757,7 @@ impl TomlManifest {
deps: Option<&BTreeMap<String, MaybeWorkspaceDependency>>,
filter: impl Fn(&TomlDependency) -> bool,
) -> CargoResult<Option<BTreeMap<String, MaybeWorkspaceDependency>>> {
- let deps = match deps {
- Some(deps) => deps,
- None => return Ok(None),
- };
+ let Some(deps) = deps else { return Ok(None) };
let deps = deps
.iter()
.filter(|(_k, v)| {
@@ -1940,6 +1837,13 @@ impl TomlManifest {
}
}
+ if !package_root.is_dir() {
+ bail!(
+ "package root '{}' is not a directory",
+ package_root.display()
+ );
+ };
+
let mut nested_paths = vec![];
let mut warnings = vec![];
let mut errors = vec![];
@@ -1979,7 +1883,7 @@ impl TomlManifest {
let mut inheritable = toml_config.package.clone().unwrap_or_default();
inheritable.update_ws_path(package_root.to_path_buf());
inheritable.update_deps(toml_config.dependencies.clone());
- let lints = parse_unstable_lints(toml_config.lints.clone(), config, &mut warnings)?;
+ let lints = toml_config.lints.clone();
let lints = verify_lints(lints)?;
inheritable.update_lints(lints);
if let Some(ws_deps) = &inheritable.dependencies {
@@ -2065,11 +1969,7 @@ impl TomlManifest {
let rust_version = rust_version
.clone()
.resolve("rust_version", || inherit()?.rust_version())?;
- let req = match semver::VersionReq::parse(&rust_version) {
- // Exclude semver operators like `^` and pre-release identifiers
- Ok(req) if rust_version.chars().all(|c| c.is_ascii_digit() || c == '.') => req,
- _ => bail!("`rust-version` must be a value like \"1.32\""),
- };
+ let req = rust_version.caret_req();
if let Some(first_version) = edition.first_version() {
let unsupported =
semver::Version::new(first_version.major, first_version.minor - 1, 9999);
@@ -2083,7 +1983,7 @@ impl TomlManifest {
)
}
}
- Some(rust_version.clone())
+ Some(rust_version)
} else {
None
};
@@ -2173,9 +2073,8 @@ impl TomlManifest {
workspace_config: &WorkspaceConfig,
inherit_cell: &LazyCell<InheritableFields>,
) -> CargoResult<Option<BTreeMap<String, MaybeWorkspaceDependency>>> {
- let dependencies = match new_deps {
- Some(dependencies) => dependencies,
- None => return Ok(None),
+ let Some(dependencies) = new_deps else {
+ return Ok(None);
};
let inheritable = || {
@@ -2245,10 +2144,11 @@ impl TomlManifest {
&inherit_cell,
)?;
- let lints =
- parse_unstable_lints::<MaybeWorkspaceLints>(me.lints.clone(), config, cx.warnings)?
- .map(|mw| mw.resolve("lints", || inherit()?.lints()))
- .transpose()?;
+ let lints = me
+ .lints
+ .clone()
+ .map(|mw| mw.resolve(|| inherit()?.lints()))
+ .transpose()?;
let lints = verify_lints(lints)?;
let default = TomlLints::default();
let rustflags = lints_to_rustflags(lints.as_ref().unwrap_or(&default));
@@ -2319,7 +2219,7 @@ impl TomlManifest {
let mut names_sources = BTreeMap::new();
for dep in &deps {
let name = dep.name_in_toml();
- let prev = names_sources.insert(name.to_string(), dep.source_id());
+ let prev = names_sources.insert(name, dep.source_id());
if prev.is_some() && prev != Some(dep.source_id()) {
bail!(
"Dependency '{}' has different source paths depending on the build \
@@ -2350,7 +2250,7 @@ impl TomlManifest {
deps,
me.features.as_ref().unwrap_or(&empty_features),
package.links.as_deref(),
- rust_version.as_deref().map(InternedString::new),
+ rust_version.clone(),
)?;
let metadata = ManifestMetadata {
@@ -2420,7 +2320,6 @@ impl TomlManifest {
links: package.links.clone(),
rust_version: package
.rust_version
- .clone()
.map(|mw| mw.resolve("rust-version", || inherit()?.rust_version()))
.transpose()?,
};
@@ -2550,8 +2449,10 @@ impl TomlManifest {
.badges
.as_ref()
.map(|_| MaybeWorkspace::Defined(metadata.badges.clone())),
- lints: lints
- .map(|lints| toml::Value::try_from(MaybeWorkspaceLints::Defined(lints)).unwrap()),
+ lints: lints.map(|lints| MaybeWorkspaceLints {
+ workspace: false,
+ lints,
+ }),
};
let mut manifest = Manifest::new(
summary,
@@ -2683,7 +2584,7 @@ impl TomlManifest {
let mut inheritable = toml_config.package.clone().unwrap_or_default();
inheritable.update_ws_path(root.to_path_buf());
inheritable.update_deps(toml_config.dependencies.clone());
- let lints = parse_unstable_lints(toml_config.lints.clone(), config, &mut warnings)?;
+ let lints = toml_config.lints.clone();
let lints = verify_lints(lints)?;
inheritable.update_lints(lints);
let ws_root_config = WorkspaceRootConfig::new(
@@ -2756,8 +2657,8 @@ impl TomlManifest {
replacement.unused_keys(),
&mut cx.warnings,
);
- dep.set_version_req(VersionReq::exact(version))
- .lock_version(version);
+ dep.set_version_req(OptVersionReq::exact(&version))
+ .lock_version(&version);
replace.push((spec, dep));
}
Ok(replace)
@@ -2830,55 +2731,6 @@ impl TomlManifest {
}
}
-fn parse_unstable_lints<T: Deserialize<'static>>(
- lints: Option<toml::Value>,
- config: &Config,
- warnings: &mut Vec<String>,
-) -> CargoResult<Option<T>> {
- let Some(lints) = lints else {
- return Ok(None);
- };
-
- if !config.cli_unstable().lints {
- warn_for_lint_feature(config, warnings);
- return Ok(None);
- }
-
- lints.try_into().map(Some).map_err(|err| err.into())
-}
-
-fn warn_for_lint_feature(config: &Config, warnings: &mut Vec<String>) {
- use std::fmt::Write as _;
-
- let key_name = "lints";
- let feature_name = "lints";
-
- let mut message = String::new();
-
- let _ = write!(
- message,
- "unused manifest key `{key_name}` (may be supported in a future version)"
- );
- if config.nightly_features_allowed {
- let _ = write!(
- message,
- "
-
-consider passing `-Z{feature_name}` to enable this feature."
- );
- } else {
- let _ = write!(
- message,
- "
-
-this Cargo does not support nightly features, but if you
-switch to nightly channel you can pass
-`-Z{feature_name}` to enable this feature.",
- );
- }
- warnings.push(message);
-}
-
fn verify_lints(lints: Option<TomlLints>) -> CargoResult<Option<TomlLints>> {
let Some(lints) = lints else {
return Ok(None);
@@ -3302,7 +3154,7 @@ impl<P: ResolveToPath + Clone> DetailedTomlDependency<P> {
self.target.as_deref(),
) {
if cx.config.cli_unstable().bindeps {
- let artifact = Artifact::parse(artifact, is_lib, target)?;
+ let artifact = Artifact::parse(&artifact.0, is_lib, target)?;
if dep.kind() != DepKind::Build
&& artifact.target() == Some(ArtifactTarget::BuildDependencyAssumeTarget)
{
@@ -3493,17 +3345,63 @@ impl fmt::Debug for PathValue {
}
}
+#[derive(Deserialize, Serialize, Debug, Clone)]
+#[serde(expecting = "a lints table")]
+pub struct MaybeWorkspaceLints {
+ #[serde(skip_serializing_if = "is_false")]
+ #[serde(deserialize_with = "bool_no_false", default)]
+ workspace: bool,
+ #[serde(flatten)]
+ lints: TomlLints,
+}
+
+fn is_false(b: &bool) -> bool {
+ !b
+}
+
+impl MaybeWorkspaceLints {
+ fn resolve<'a>(
+ self,
+ get_ws_inheritable: impl FnOnce() -> CargoResult<TomlLints>,
+ ) -> CargoResult<TomlLints> {
+ if self.workspace {
+ if !self.lints.is_empty() {
+ anyhow::bail!("cannot override `workspace.lints` in `lints`, either remove the overrides or `lints.workspace = true` and manually specify the lints");
+ }
+ get_ws_inheritable().with_context(|| {
+ "error inheriting `lints` from workspace root manifest's `workspace.lints`"
+ })
+ } else {
+ Ok(self.lints)
+ }
+ }
+}
+
pub type TomlLints = BTreeMap<String, TomlToolLints>;
pub type TomlToolLints = BTreeMap<String, TomlLint>;
-#[derive(Serialize, Deserialize, Debug, Clone)]
+#[derive(Serialize, Debug, Clone)]
#[serde(untagged)]
pub enum TomlLint {
Level(TomlLintLevel),
Config(TomlLintConfig),
}
+impl<'de> Deserialize<'de> for TomlLint {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ UntaggedEnumVisitor::new()
+ .string(|string| {
+ TomlLintLevel::deserialize(string.into_deserializer()).map(TomlLint::Level)
+ })
+ .map(|map| map.deserialize().map(TomlLint::Config))
+ .deserialize(deserializer)
+ }
+}
+
impl TomlLint {
fn level(&self) -> TomlLintLevel {
match self {
@@ -3547,3 +3445,20 @@ impl TomlLintLevel {
}
}
}
+
+#[derive(Copy, Clone, Debug)]
+#[non_exhaustive]
+struct InvalidCargoFeatures {}
+
+impl<'de> de::Deserialize<'de> for InvalidCargoFeatures {
+ fn deserialize<D>(_d: D) -> Result<Self, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ {
+ use serde::de::Error as _;
+
+ Err(D::Error::custom(
+ "the field `cargo-features` should be set at the top of Cargo.toml before any tables",
+ ))
+ }
+}
diff --git a/src/tools/cargo/src/cargo/util/toml/targets.rs b/src/tools/cargo/src/cargo/util/toml/targets.rs
index a7e30c61b..afc4f258f 100644
--- a/src/tools/cargo/src/cargo/util/toml/targets.rs
+++ b/src/tools/cargo/src/cargo/util/toml/targets.rs
@@ -171,10 +171,7 @@ fn clean_lib(
}),
};
- let lib = match lib {
- Some(ref lib) => lib,
- None => return Ok(None),
- };
+ let Some(ref lib) = lib else { return Ok(None) };
lib.validate_proc_macro(warnings);
lib.validate_crate_types("library", warnings);
@@ -747,7 +744,7 @@ https://github.com/rust-lang/cargo/issues/5330",
fn inferred_to_toml_targets(inferred: &[(String, PathBuf)]) -> Vec<TomlTarget> {
inferred
.iter()
- .map(|&(ref name, ref path)| TomlTarget {
+ .map(|(name, path)| TomlTarget {
name: Some(name.clone()),
path: Some(PathValue(path.clone())),
..TomlTarget::new()
@@ -929,8 +926,8 @@ fn target_path(
let mut matching = inferred
.iter()
- .filter(|&&(ref n, _)| n == &name)
- .map(|&(_, ref p)| p.clone());
+ .filter(|(n, _)| n == &name)
+ .map(|(_, p)| p.clone());
let first = matching.next();
let second = matching.next();
diff --git a/src/tools/cargo/src/doc/book.toml b/src/tools/cargo/src/doc/book.toml
index 1dd1f8e0f..ae8280d28 100644
--- a/src/tools/cargo/src/doc/book.toml
+++ b/src/tools/cargo/src/doc/book.toml
@@ -6,3 +6,4 @@ author = "Alex Crichton, Steve Klabnik and Carol Nichols, with contributions fro
curly-quotes = true # Enable smart-punctuation feature for more than quotes.
git-repository-url = "https://github.com/rust-lang/cargo/tree/master/src/doc/src"
edit-url-template = "https://github.com/rust-lang/cargo/edit/master/src/doc/{path}"
+search.use-boolean-and = true
diff --git a/src/tools/cargo/src/doc/contrib/src/SUMMARY.md b/src/tools/cargo/src/doc/contrib/src/SUMMARY.md
index 053a9db35..f8796b3f3 100644
--- a/src/tools/cargo/src/doc/contrib/src/SUMMARY.md
+++ b/src/tools/cargo/src/doc/contrib/src/SUMMARY.md
@@ -7,6 +7,7 @@
- [Working on Cargo](./process/working-on-cargo.md)
- [Release process](./process/release.md)
- [Unstable features](./process/unstable.md)
+ - [Security issues](./process/security.md)
- [Design Principles](./design.md)
- [Implementing a Change](./implementation/index.md)
- [Architecture](./implementation/architecture.md)
diff --git a/src/tools/cargo/src/doc/contrib/src/implementation/debugging.md b/src/tools/cargo/src/doc/contrib/src/implementation/debugging.md
index 03940e2ff..c3a8e0423 100644
--- a/src/tools/cargo/src/doc/contrib/src/implementation/debugging.md
+++ b/src/tools/cargo/src/doc/contrib/src/implementation/debugging.md
@@ -16,12 +16,12 @@ CARGO_LOG=debug cargo generate-lockfile
CARGO_LOG=cargo::core::resolver=trace cargo generate-lockfile
# This will print lots of info about the download process. `trace` prints even more.
-CARGO_HTTP_DEBUG=true CARGO_LOG=cargo::ops::registry=debug cargo fetch
+CARGO_HTTP_DEBUG=true CARGO_LOG=network=debug cargo fetch
# This is an important command for diagnosing fingerprint issues.
CARGO_LOG=cargo::core::compiler::fingerprint=trace cargo build
```
[`tracing`]: https://docs.rs/tracing
-[directive]: https://docs.rs/tracing_subscriber/filter/struct.EnvFilter.html#directives
-[shorthand macros]: https://docs.rs/tracing/index.html#shorthand-macros
+[directive]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives
+[shorthand macros]: https://docs.rs/tracing/latest/tracing/index.html#shorthand-macros
diff --git a/src/tools/cargo/src/doc/contrib/src/process/security.md b/src/tools/cargo/src/doc/contrib/src/process/security.md
new file mode 100644
index 000000000..84e587d7a
--- /dev/null
+++ b/src/tools/cargo/src/doc/contrib/src/process/security.md
@@ -0,0 +1,136 @@
+# Security issues
+
+Issues involving reporting a security vulnerability in cargo usually start by following the [Rust security policy].
+The Security Response Working Group ("the WG") is responsible for running the process of handling the response to a security issue.
+Their process is documented at [Handling Reports].
+This document gives an overview of the process from a Cargo team member's perspective.
+
+The general order of events happens as follows:
+
+1. The "reporter" (even if it is a Cargo team member) reports an issue to <security@rust-lang.org>.
+1. The WG will evaluate if the report is credible, and manages responses to the reporter.
+1. The WG will start a private Zulip stream to coordinate discussion and plans for a fix.
+1. The WG will pull in one or more team members into the Zulip stream ("responders").
+ - Security vulnerabilities are **embargoed** until they are released publicly.
+ People who are brought into these discussions should **not** discuss the issue with *anyone* outside of the group, including your employer, without first consulting The WG.
+1. A discussion then starts to evaluate the severity of the issue and what possible solutions should be considered.
+ This includes figuring out who will volunteer to actually develop the patches to resolve the issue, and who will review it.
+1. The WG will create a temporary private fork of the `rust-lang/cargo` repo using GitHub's [repository security advisory][github-advisory] system.
+ This provides a space where changes can be securely posted, and the security advisory can be drafted.
+ See ["Collaborating in a temporary private fork"][private-fork] for some screenshots of what this looks like.
+ GitHub includes instructions on how to work with the fork.
+
+ Beware that the private fork has some limitations, such as not supporting CI, or (for some weird reason) not supporting syntax highlighting.
+1. Someone will need to review the patches and make sure everyone agrees on the solution.
+ This may also involve the WG conferring with the reporter to validate the fix.
+1. Create a rollout plan.
+ This includes deciding if there will be a new patch release of Rust, or if it should wait for the next stable release, or whether to remove the embargo on the fix.
+1. The WG will handle drafting a Security Advisory using GitHub's Security Advisory ("GHSA") system.
+ [GHSA-r5w3-xm58-jv6j] is an example of what this looks like.
+ This process also involves reserving a [CVE](https://www.cve.org/) number, where the report will eventually be posted.
+
+ The responders should carefully review the report to make sure it is correct.
+
+ This process may also involve deciding on the CVSS score.
+ There are a bunch of calculators on the web where you can see how this works (such as the [FIRST CVSS Calculator][calc], or you can view GitHub's calculator by drafting a security advisory in one of your personal repos).
+ FIRST has a [user guide][first-guide] for deciding how to score each characteristic.
+1. If it is decided to do a patch release of Rust, the general overview of steps is:
+ 1. Finalizing the patches.
+ This includes all the little details like updating changelogs, version numbers, and such.
+ 1. Preparing PRs in the private fork against the stable, beta, and nightly (master) branches.
+ 1. The WG handles creating a private fork of `rust-lang/rust` to prepare the point release.
+ This usually includes changes for stable, beta, and nightly.
+ 1. The WG handles posting patches in various places (such as mailing lists), possibly several days in advance.
+ 1. The WG handles posting public PRs to `rust-lang/rust` to incorporate the fix and prepare a new release.
+ 1. The WG handles announcing everything, including publishing the GHSA, publishing a blog post, and several other places.
+
+## External dependency patches
+
+Sometimes it may be necessary to make changes to external dependencies to support a fix.
+This can make things complicated.
+If the change is by itself benign and not directly related to the security issue,
+then it may be safe to publicly propose the change (but not giving context) and try to get a new release of the dependency made (though confer with the WG first!).
+However, if the issue is directly related to the dependency, then it becomes significantly more awkward.
+
+The general process for [GHSA-r5w3-xm58-jv6j] which involved a fix in `git2-rs` was handled by the responders because it is a dependency owned by the rust-lang org.
+The general outline of how we managed this is:
+
+- Pre-release:
+ 1. Created a private fork of `rust-lang/git2-rs` just like we did for `rust-lang/cargo`.
+ git2-rs also had its own Security Advisory just like cargo did.
+ 1. Created and reviewed PRs in the private fork for the fixes.
+ - The PRs in the `rust-lang/cargo` private fork had to have a temporary `[patch]` git dependency on the `git2-rs` private fork.
+ 1. Before the release, the PRs were changed to remove the `[patch]`, and pretend as-if git2-rs had already been published.
+- Showtime:
+ 1. The git2-rs changes were publicly merged, and a new release was published to crates.io.
+ 1. The cargo PR was merged to cargo's stable branch.
+ 1. The private rust-lang/rust PR updated the cargo submodule and updated `Cargo.lock` to pick up the new git2 dependencies.
+ 1. Release proceeds as normal (publish both GHSA, create release, etc.).
+- Post-release:
+ 1. Various forward ports were created in git2-rs, and new releases were made.
+
+If the change is in a crate not managed by any responder, then confer with the WG on a strategy.
+One option is to create a temporary fork used for the security response that will be removed as soon as the security advisory is released and a new public release of the dependency is made with the fix.
+
+## Checklist
+
+There are a lot of details to handle, and it can be a bit of a challenge under time pressure.
+The following is a checklist of some items to pay attention to during the process.
+
+Pre-release:
+- [ ] Check for any SemVer-incompatible changes in the public API of any crates that are modified.
+ - Try to avoid these if at all possible.
+ Although not a severe problem, making Cargo's version number drift farther from Rust's can contribute to confusion.
+ - If a SemVer-breaking release is made to a dependency, make sure this is coordinated correctly between the stable, beta, and master branches.
+- [ ] With a checkout of the proposed fixes, run as much of cargo's CI testsuite locally as you can.
+ Since private forks don't support CI, the responders will be responsible for making sure all tests pass.
+ Enlist other responders if you don't have the necessary systems like Windows.
+- [ ] Manually exercise the fix locally.
+ Since we will essentially have *no* nightly testing, the responders are responsible for making sure things work.
+ Try to consider all the different environments users may be using.
+- [ ] Make sure any comments or docs that need updating get updated.
+- [ ] Review the git commit messages of the patch.
+ Make sure they clearly and accurately reflect what is being changed and why.
+ Clean up the commit history if it goes through several revisions during review.
+- [ ] Make sure that the *public* cargo repo's stable and beta branches are in a state where they are passing CI.
+ This may require backporting changes that fix problems that have already been fixed in master.
+ This can be done publicly at any time, and helps with ensuring a smooth process once the security issue is released.
+ (The WG may disable branch protections to push directly to the stable branch, but this step is still useful to assist with local testing and the beta branch.)
+- [ ] After the fix is approved, create backports to the stable and beta master branches and post PRs to the private fork.
+- [ ] If any internal dependencies are changed, make sure their versions are bumped appropriately, and dependency specifications are updated (stable, beta, and master branches).
+- [ ] Thoroughly test the stable and beta PRs locally, too. We want to make sure everything goes smoothly, and we can't assume that just because a patch applied cleanly that there won't be issues.
+- [ ] Make sure cargo's version in [`Cargo.toml`] is updated correctly on the stable branch private PR.
+- [ ] Make sure cargo's `Cargo.lock` is updated (stable, beta, master branches).
+- [ ] Update [`CHANGELOG.md`] on cargo's master branch private PR.
+- [ ] Update [`RELEASES.md`] on rust's master branch private PR (and stable and beta?).
+- [ ] Remove any temporary things in the patch, like a temporary `[patch]` table.
+
+Showtime:
+- [ ] Publish any embargoed external dependencies to crates.io.
+- [ ] (WG) Merge the cargo stable change.
+- [ ] (WG) Update the cargo submodule in the rust-lang/rust private PR to point to the new stable commit.
+ - [ ] Also update `Cargo.lock`.
+- [ ] (WG) Make a new stable release.
+- [ ] (WG) Publish the GHSA.
+- [ ] (WG) Send announcements.
+- [ ] Make sure stable, beta, and master branches of `rust-lang/cargo` get updated.
+- [ ] Make sure stable, beta, and master branches of `rust-lang/rust` get updated, pointing to the correct submodule versions.
+- [ ] If any external dependencies are updated, make sure their back or forward ports are handled.
+
+Post release:
+- [ ] Verify that the appropriate crates are published on crates.io.
+- [ ] Verify that `rust-lang/cargo` got a new tag.
+- [ ] Verify that the patches were backported to the correct branches in the `rust-lang/cargo` repository (stable, beta, and master).
+- [ ] Verify that the cargo submodule is updated on the correct branches in the `rust-lang/rust` repository (stable, beta, and master).
+- [ ] Follow up on any non-critical tasks that were identified during review.
+
+[Rust security policy]: https://www.rust-lang.org/policies/security
+[github-advisory]: https://docs.github.com/en/code-security/security-advisories/repository-security-advisories
+[private-fork]: https://docs.github.com/en/code-security/security-advisories/repository-security-advisories/collaborating-in-a-temporary-private-fork-to-resolve-a-repository-security-vulnerability
+[calc]: https://www.first.org/cvss/calculator
+[GHSA-r5w3-xm58-jv6j]: https://github.com/rust-lang/cargo/security/advisories/GHSA-r5w3-xm58-jv6j
+[handling reports]: https://github.com/rust-lang/wg-security-response/blob/main/docs/handling-reports.md
+[first-guide]: https://www.first.org/cvss/user-guide
+[`CHANGELOG.md`]: https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md
+[`Cargo.toml`]: https://github.com/rust-lang/cargo/blob/master/Cargo.toml
+[`RELEASES.md`]: https://github.com/rust-lang/rust/blob/master/RELEASES.md
diff --git a/src/tools/cargo/src/doc/man/cargo-add.md b/src/tools/cargo/src/doc/man/cargo-add.md
index 3c15fc9d5..21c222a39 100644
--- a/src/tools/cargo/src/doc/man/cargo-add.md
+++ b/src/tools/cargo/src/doc/man/cargo-add.md
@@ -1,7 +1,7 @@
# cargo-add(1)
-
-{{*set actionverb="Add"}}
-{{*set nouns="adds"}}
+{{~*set command="add"}}
+{{~*set actionverb="Add"}}
+{{~*set nouns="adds"}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-bench.md b/src/tools/cargo/src/doc/man/cargo-bench.md
index 18771c3d2..a2a602847 100644
--- a/src/tools/cargo/src/doc/man/cargo-bench.md
+++ b/src/tools/cargo/src/doc/man/cargo-bench.md
@@ -1,7 +1,8 @@
# cargo-bench(1)
-{{*set actionverb="Benchmark"}}
-{{*set nouns="benchmarks"}}
-{{*set multitarget=true}}
+{{~*set command="bench"}}
+{{~*set actionverb="Benchmark"}}
+{{~*set nouns="benchmarks"}}
+{{~*set multitarget=true}}
## NAME
@@ -157,9 +158,16 @@ Rust test harness runs benchmarks serially in a single thread.
{{#options}}
{{> options-jobs }}
-{{> options-keep-going }}
{{/options}}
+While `cargo bench` involves compilation, it does not provide a `--keep-going`
+flag. Use `--no-fail-fast` to run as many benchmarks as possible without
+stopping at the first failure. To "compile" as many benchmarks as possible, use
+`--benches` to build benchmark binaries separately. For example:
+
+ cargo build --benches --release --keep-going
+ cargo bench --no-fail-fast
+
{{> section-environment }}
{{> section-exit-status }}
diff --git a/src/tools/cargo/src/doc/man/cargo-build.md b/src/tools/cargo/src/doc/man/cargo-build.md
index 986144443..18d6eeae8 100644
--- a/src/tools/cargo/src/doc/man/cargo-build.md
+++ b/src/tools/cargo/src/doc/man/cargo-build.md
@@ -1,6 +1,7 @@
# cargo-build(1)
-{{*set actionverb="Build"}}
-{{*set multitarget=true}}
+{{~*set command="build"}}
+{{~*set actionverb="Build"}}
+{{~*set multitarget=true}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-check.md b/src/tools/cargo/src/doc/man/cargo-check.md
index 055adff0d..92c8a5d07 100644
--- a/src/tools/cargo/src/doc/man/cargo-check.md
+++ b/src/tools/cargo/src/doc/man/cargo-check.md
@@ -1,6 +1,7 @@
# cargo-check(1)
-{{*set actionverb="Check"}}
-{{*set multitarget=true}}
+{{~*set command="check"}}
+{{~*set actionverb="Check"}}
+{{~*set multitarget=true}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-clean.md b/src/tools/cargo/src/doc/man/cargo-clean.md
index 3222f7bb0..ee920b223 100644
--- a/src/tools/cargo/src/doc/man/cargo-clean.md
+++ b/src/tools/cargo/src/doc/man/cargo-clean.md
@@ -1,6 +1,7 @@
# cargo-clean(1)
-{{*set actionverb="Clean"}}
-{{*set multitarget=true}}
+{{~*set command="clean"}}
+{{~*set actionverb="Clean"}}
+{{~*set multitarget=true}}
## NAME
@@ -35,6 +36,11 @@ multiple times. See {{man "cargo-pkgid" 1}} for the SPEC format.
{{#options}}
+{{#option "`--dry-run`" }}
+Displays a summary of what would be deleted without deleting anything.
+Use with `--verbose` to display the actual files that would be deleted.
+{{/option}}
+
{{#option "`--doc`" }}
This option will cause `cargo clean` to remove only the `doc` directory in
the target directory.
diff --git a/src/tools/cargo/src/doc/man/cargo-doc.md b/src/tools/cargo/src/doc/man/cargo-doc.md
index 9d5b77648..b2e273ee5 100644
--- a/src/tools/cargo/src/doc/man/cargo-doc.md
+++ b/src/tools/cargo/src/doc/man/cargo-doc.md
@@ -1,6 +1,7 @@
# cargo-doc(1)
-{{*set actionverb="Document"}}
-{{*set multitarget=true}}
+{{~*set command="doc"}}
+{{~*set actionverb="Document"}}
+{{~*set multitarget=true}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-fetch.md b/src/tools/cargo/src/doc/man/cargo-fetch.md
index c31166a9b..b8a0eb666 100644
--- a/src/tools/cargo/src/doc/man/cargo-fetch.md
+++ b/src/tools/cargo/src/doc/man/cargo-fetch.md
@@ -1,7 +1,8 @@
# cargo-fetch(1)
-{{*set actionverb="Fetch"}}
-{{*set target-default-to-all-arch=true}}
-{{*set multitarget=true}}
+{{~*set command="fetch"}}
+{{~*set actionverb="Fetch"}}
+{{~*set target-default-to-all-arch=true}}
+{{~*set multitarget=true}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-fix.md b/src/tools/cargo/src/doc/man/cargo-fix.md
index 64fe29944..89fb81cef 100644
--- a/src/tools/cargo/src/doc/man/cargo-fix.md
+++ b/src/tools/cargo/src/doc/man/cargo-fix.md
@@ -1,6 +1,7 @@
# cargo-fix(1)
-{{*set actionverb="Fix"}}
-{{*set multitarget=true}}
+{{~*set command="fix"}}
+{{~*set actionverb="Fix"}}
+{{~*set multitarget=true}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-install.md b/src/tools/cargo/src/doc/man/cargo-install.md
index e6786318f..5431bdb79 100644
--- a/src/tools/cargo/src/doc/man/cargo-install.md
+++ b/src/tools/cargo/src/doc/man/cargo-install.md
@@ -1,6 +1,7 @@
# cargo-install(1)
-{{*set actionverb="Install"}}
-{{*set temp-target-dir=true}}
+{{~*set command="install"}}
+{{~*set actionverb="Install"}}
+{{~*set temp-target-dir=true}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-login.md b/src/tools/cargo/src/doc/man/cargo-login.md
index 54c823d2d..197636da8 100644
--- a/src/tools/cargo/src/doc/man/cargo-login.md
+++ b/src/tools/cargo/src/doc/man/cargo-login.md
@@ -2,18 +2,25 @@
## NAME
-cargo-login --- Save an API token from the registry locally
+cargo-login --- Log in to a registry
## SYNOPSIS
-`cargo login` [_options_] [_token_]
+`cargo login` [_options_] [_token_] -- [_args_]
## DESCRIPTION
-This command will save the API token to disk so that commands that require
-authentication, such as {{man "cargo-publish" 1}}, will be automatically
-authenticated. The token is saved in `$CARGO_HOME/credentials.toml`. `CARGO_HOME`
-defaults to `.cargo` in your home directory.
+This command will run a credential provider to save a token so that commands
+that require authentication, such as {{man "cargo-publish" 1}}, will be
+automatically authenticated.
+
+For the default `cargo:token` credential provider, the token is saved
+in `$CARGO_HOME/credentials.toml`. `CARGO_HOME` defaults to `.cargo`
+in your home directory.
+
+If a registry has a credential-provider specified, it will be used. Otherwise,
+the providers from the config value `registry.global-credential-providers` will
+be attempted, starting from the end of the list.
If the _token_ argument is not specified, it will be read from stdin.
@@ -43,9 +50,13 @@ Take care to keep the token secret, it should not be shared with anyone else.
## EXAMPLES
-1. Save the API token to disk:
+1. Save the token for the default registry:
cargo login
+2. Save the token for a specific registry:
+
+ cargo login --registry my-registry
+
## SEE ALSO
{{man "cargo" 1}}, {{man "cargo-logout" 1}}, {{man "cargo-publish" 1}}
diff --git a/src/tools/cargo/src/doc/man/cargo-logout.md b/src/tools/cargo/src/doc/man/cargo-logout.md
index f9c0db58c..d8277bf54 100644
--- a/src/tools/cargo/src/doc/man/cargo-logout.md
+++ b/src/tools/cargo/src/doc/man/cargo-logout.md
@@ -10,9 +10,15 @@ cargo-logout --- Remove an API token from the registry locally
## DESCRIPTION
-This command will remove the API token from the local credential storage.
-Credentials are stored in `$CARGO_HOME/credentials.toml` where `$CARGO_HOME`
-defaults to `.cargo` in your home directory.
+This command will run a credential provider to remove a saved token.
+
+For the default `cargo:token` credential provider, credentials are stored
+in `$CARGO_HOME/credentials.toml` where `$CARGO_HOME` defaults to `.cargo`
+in your home directory.
+
+If a registry has a credential-provider specified, it will be used. Otherwise,
+the providers from the config value `registry.global-credential-providers` will
+be attempted, starting from the end of the list.
If `--registry` is not specified, then the credentials for the default
registry will be removed (configured by
diff --git a/src/tools/cargo/src/doc/man/cargo-metadata.md b/src/tools/cargo/src/doc/man/cargo-metadata.md
index 8efb29a97..b7d04530d 100644
--- a/src/tools/cargo/src/doc/man/cargo-metadata.md
+++ b/src/tools/cargo/src/doc/man/cargo-metadata.md
@@ -27,7 +27,7 @@ for a Rust API for reading the metadata.
Within the same output format version, the compatibility is maintained, except
some scenarios. The following is a non-exhaustive list of changes that are not
-considersed as incompatibile:
+considersed as incompatible:
* **Adding new fields** — New fields will be added when needed. Reserving this
helps Cargo evolve without bumping the format version too often.
diff --git a/src/tools/cargo/src/doc/man/cargo-package.md b/src/tools/cargo/src/doc/man/cargo-package.md
index 2000353cc..5057e59fe 100644
--- a/src/tools/cargo/src/doc/man/cargo-package.md
+++ b/src/tools/cargo/src/doc/man/cargo-package.md
@@ -1,7 +1,8 @@
# cargo-package(1)
-{{*set actionverb="Package"}}
-{{*set noall=true}}
-{{*set multitarget=true}}
+{{~*set command="package"}}
+{{~*set actionverb="Package"}}
+{{~*set noall=true}}
+{{~*set multitarget=true}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-publish.md b/src/tools/cargo/src/doc/man/cargo-publish.md
index 4ccb5b529..c5e64db80 100644
--- a/src/tools/cargo/src/doc/man/cargo-publish.md
+++ b/src/tools/cargo/src/doc/man/cargo-publish.md
@@ -1,6 +1,7 @@
# cargo-publish(1)
-{{*set actionverb="Publish"}}
-{{*set multitarget=true}}
+{{~*set command="publish"}}
+{{~*set actionverb="Publish"}}
+{{~*set multitarget=true}}
## NAME
@@ -21,8 +22,11 @@ following steps:
- Checks the `package.publish` key in the manifest for restrictions on
which registries you are allowed to publish to.
2. Create a `.crate` file by following the steps in {{man "cargo-package" 1}}.
-3. Upload the crate to the registry. Note that the server will perform
- additional checks on the crate.
+3. Upload the crate to the registry. The server will perform additional
+ checks on the crate.
+4. The client will poll waiting for the package to appear in the index,
+ and may timeout. In that case, you will need to check for completion
+ manually. This timeout does not affect the upload.
This command requires you to be authenticated with either the `--token` option
or using {{man "cargo-login" 1}}.
diff --git a/src/tools/cargo/src/doc/man/cargo-remove.md b/src/tools/cargo/src/doc/man/cargo-remove.md
index e38589ccb..0bdb04ac6 100644
--- a/src/tools/cargo/src/doc/man/cargo-remove.md
+++ b/src/tools/cargo/src/doc/man/cargo-remove.md
@@ -1,6 +1,7 @@
# cargo-remove(1)
-{{*set actionverb="Remove"}}
-{{*set nouns="removes"}}
+{{~*set command="remove"}}
+{{~*set actionverb="Remove"}}
+{{~*set nouns="removes"}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-run.md b/src/tools/cargo/src/doc/man/cargo-run.md
index 034a35f23..8a8ddb309 100644
--- a/src/tools/cargo/src/doc/man/cargo-run.md
+++ b/src/tools/cargo/src/doc/man/cargo-run.md
@@ -1,5 +1,6 @@
# cargo-run(1)
-{{*set actionverb="Run"}}
+{{~*set command="run"}}
+{{~*set actionverb="Run"}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-rustc.md b/src/tools/cargo/src/doc/man/cargo-rustc.md
index 18c0856f2..279c6dbd1 100644
--- a/src/tools/cargo/src/doc/man/cargo-rustc.md
+++ b/src/tools/cargo/src/doc/man/cargo-rustc.md
@@ -1,6 +1,7 @@
# cargo-rustc(1)
-{{*set actionverb="Build"}}
-{{*set multitarget=true}}
+{{~*set command="rustc"}}
+{{~*set actionverb="Build"}}
+{{~*set multitarget=true}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-rustdoc.md b/src/tools/cargo/src/doc/man/cargo-rustdoc.md
index 23be579e9..39f70713c 100644
--- a/src/tools/cargo/src/doc/man/cargo-rustdoc.md
+++ b/src/tools/cargo/src/doc/man/cargo-rustdoc.md
@@ -1,6 +1,7 @@
# cargo-rustdoc(1)
-{{*set actionverb="Document"}}
-{{*set multitarget=true}}
+{{~*set command="rustdoc"}}
+{{~*set actionverb="Document"}}
+{{~*set multitarget=true}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-test.md b/src/tools/cargo/src/doc/man/cargo-test.md
index cba98b20d..1755ab7de 100644
--- a/src/tools/cargo/src/doc/man/cargo-test.md
+++ b/src/tools/cargo/src/doc/man/cargo-test.md
@@ -1,7 +1,8 @@
# cargo-test(1)
-{{*set actionverb="Test"}}
-{{*set nouns="tests"}}
-{{*set multitarget=true}}
+{{~*set command="test"}}
+{{~*set actionverb="Test"}}
+{{~*set nouns="tests"}}
+{{~*set multitarget=true}}
## NAME
@@ -190,6 +191,14 @@ includes an option to control the number of threads used:
{{/options}}
+While `cargo test` involves compilation, it does not provide a `--keep-going`
+flag. Use `--no-fail-fast` to run as many tests as possible without stopping at
+the first failure. To "compile" as many tests as possible, use `--tests` to
+build test binaries separately. For example:
+
+ cargo build --tests --keep-going
+ cargo test --tests --no-fail-fast
+
{{> section-environment }}
{{> section-exit-status }}
diff --git a/src/tools/cargo/src/doc/man/cargo-tree.md b/src/tools/cargo/src/doc/man/cargo-tree.md
index 3e1da20df..1bb52883c 100644
--- a/src/tools/cargo/src/doc/man/cargo-tree.md
+++ b/src/tools/cargo/src/doc/man/cargo-tree.md
@@ -1,6 +1,7 @@
# cargo-tree(1)
-{{*set actionverb="Display"}}
-{{*set noall=true}}
+{{~*set command="tree"}}
+{{~*set actionverb="Display"}}
+{{~*set noall=true}}
## NAME
diff --git a/src/tools/cargo/src/doc/man/cargo-update.md b/src/tools/cargo/src/doc/man/cargo-update.md
index e91606a6a..b392b8314 100644
--- a/src/tools/cargo/src/doc/man/cargo-update.md
+++ b/src/tools/cargo/src/doc/man/cargo-update.md
@@ -6,7 +6,7 @@ cargo-update --- Update dependencies as recorded in the local lock file
## SYNOPSIS
-`cargo update` [_options_]
+`cargo update` [_options_] _spec_
## DESCRIPTION
@@ -20,26 +20,26 @@ latest available versions.
{{#options}}
-{{#option "`-p` _spec_..." "`--package` _spec_..." }}
+{{#option "_spec_..." }}
Update only the specified packages. This flag may be specified
multiple times. See {{man "cargo-pkgid" 1}} for the SPEC format.
-If packages are specified with the `-p` flag, then a conservative update of
+If packages are specified with _spec_, then a conservative update of
the lockfile will be performed. This means that only the dependency specified
by SPEC will be updated. Its transitive dependencies will be updated only if
SPEC cannot be updated without updating dependencies. All other dependencies
will remain locked at their currently recorded versions.
-If `-p` is not specified, all dependencies are updated.
+If _spec_ is not specified, all dependencies are updated.
{{/option}}
-{{#option "`--aggressive`" }}
-When used with `-p`, dependencies of _spec_ are forced to update as well.
+{{#option "`--recursive`" }}
+When used with _spec_, dependencies of _spec_ are forced to update as well.
Cannot be used with `--precise`.
{{/option}}
{{#option "`--precise` _precise_" }}
-When used with `-p`, allows you to specify a specific version number to set
+When used with _spec_, allows you to specify a specific version number to set
the package to. If the package comes from a git repository, this can be a git
revision (such as a SHA hash or tag).
{{/option}}
@@ -87,11 +87,11 @@ Displays what would be updated, but doesn't actually write the lockfile.
2. Update only specific dependencies:
- cargo update -p foo -p bar
+ cargo update foo bar
3. Set a specific dependency to a specific version:
- cargo update -p foo --precise 1.2.3
+ cargo update foo --precise 1.2.3
## SEE ALSO
{{man "cargo" 1}}, {{man "cargo-generate-lockfile" 1}}
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-bench.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-bench.txt
index 9610b72f0..796fbd11b 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-bench.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-bench.txt
@@ -413,10 +413,14 @@ OPTIONS
If a string default is provided, it sets the value back to defaults.
Should not be 0.
- --keep-going
- Build as many crates in the dependency graph as possible, rather
- than aborting the build on the first one that fails to build.
- Unstable, requires -Zunstable-options.
+ While cargo bench involves compilation, it does not provide a
+ --keep-going flag. Use --no-fail-fast to run as many benchmarks as
+ possible without stopping at the first failure. To “compile” as many
+ benchmarks as possible, use --benches to build benchmark binaries
+ separately. For example:
+
+ cargo build --benches --release --keep-going
+ cargo bench --no-fail-fast
ENVIRONMENT
See the reference
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-build.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-build.txt
index e396410d3..06a7a6b3c 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-build.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-build.txt
@@ -347,7 +347,13 @@ OPTIONS
--keep-going
Build as many crates in the dependency graph as possible, rather
than aborting the build on the first one that fails to build.
- Unstable, requires -Zunstable-options.
+
+ For example if the current package depends on dependencies fails and
+ works, one of which fails to build, cargo build -j1 may or may not
+ build the one that succeeds (depending on which one of the two
+ builds Cargo picked to run first), whereas cargo build -j1
+ --keep-going would definitely run both builds, even if the one run
+ first fails.
--future-incompat-report
Displays a future-incompat report for any future-incompatible
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-check.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-check.txt
index 9814f445d..b447455ee 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-check.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-check.txt
@@ -332,7 +332,13 @@ OPTIONS
--keep-going
Build as many crates in the dependency graph as possible, rather
than aborting the build on the first one that fails to build.
- Unstable, requires -Zunstable-options.
+
+ For example if the current package depends on dependencies fails and
+ works, one of which fails to build, cargo check -j1 may or may not
+ build the one that succeeds (depending on which one of the two
+ builds Cargo picked to run first), whereas cargo check -j1
+ --keep-going would definitely run both builds, even if the one run
+ first fails.
--future-incompat-report
Displays a future-incompat report for any future-incompatible
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-clean.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-clean.txt
index 33cebb719..d6b7facf4 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-clean.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-clean.txt
@@ -22,6 +22,11 @@ OPTIONS
multiple times. See cargo-pkgid(1) for the SPEC format.
Clean Options
+ --dry-run
+ Displays a summary of what would be deleted without deleting
+ anything. Use with --verbose to display the actual files that would
+ be deleted.
+
--doc
This option will cause cargo clean to remove only the doc directory
in the target directory.
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-doc.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-doc.txt
index 09f9b68c9..773d600c6 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-doc.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-doc.txt
@@ -303,7 +303,13 @@ OPTIONS
--keep-going
Build as many crates in the dependency graph as possible, rather
than aborting the build on the first one that fails to build.
- Unstable, requires -Zunstable-options.
+
+ For example if the current package depends on dependencies fails and
+ works, one of which fails to build, cargo doc -j1 may or may not
+ build the one that succeeds (depending on which one of the two
+ builds Cargo picked to run first), whereas cargo doc -j1
+ --keep-going would definitely run both builds, even if the one run
+ first fails.
ENVIRONMENT
See the reference
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-fix.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-fix.txt
index b83c360eb..3e7910ca5 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-fix.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-fix.txt
@@ -405,7 +405,13 @@ OPTIONS
--keep-going
Build as many crates in the dependency graph as possible, rather
than aborting the build on the first one that fails to build.
- Unstable, requires -Zunstable-options.
+
+ For example if the current package depends on dependencies fails and
+ works, one of which fails to build, cargo fix -j1 may or may not
+ build the one that succeeds (depending on which one of the two
+ builds Cargo picked to run first), whereas cargo fix -j1
+ --keep-going would definitely run both builds, even if the one run
+ first fails.
ENVIRONMENT
See the reference
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-install.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-install.txt
index a5b696111..02790f1d0 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-install.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-install.txt
@@ -280,7 +280,13 @@ OPTIONS
--keep-going
Build as many crates in the dependency graph as possible, rather
than aborting the build on the first one that fails to build.
- Unstable, requires -Zunstable-options.
+
+ For example if the current package depends on dependencies fails and
+ works, one of which fails to build, cargo install -j1 may or may not
+ build the one that succeeds (depending on which one of the two
+ builds Cargo picked to run first), whereas cargo install -j1
+ --keep-going would definitely run both builds, even if the one run
+ first fails.
Display Options
-v, --verbose
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-login.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-login.txt
index cce8efcfb..ae8127fc9 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-login.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-login.txt
@@ -1,16 +1,24 @@
CARGO-LOGIN(1)
NAME
- cargo-login — Save an API token from the registry locally
+ cargo-login — Log in to a registry
SYNOPSIS
- cargo login [options] [token]
+ cargo login [options] [token] – [args]
DESCRIPTION
- This command will save the API token to disk so that commands that
- require authentication, such as cargo-publish(1), will be automatically
- authenticated. The token is saved in $CARGO_HOME/credentials.toml.
- CARGO_HOME defaults to .cargo in your home directory.
+ This command will run a credential provider to save a token so that
+ commands that require authentication, such as cargo-publish(1), will be
+ automatically authenticated.
+
+ For the default cargo:token credential provider, the token is saved in
+ $CARGO_HOME/credentials.toml. CARGO_HOME defaults to .cargo in your home
+ directory.
+
+ If a registry has a credential-provider specified, it will be used.
+ Otherwise, the providers from the config value
+ registry.global-credential-providers will be attempted, starting from
+ the end of the list.
If the token argument is not specified, it will be read from stdin.
@@ -102,10 +110,14 @@ EXIT STATUS
o 101: Cargo failed to complete.
EXAMPLES
- 1. Save the API token to disk:
+ 1. Save the token for the default registry:
cargo login
+ 2. Save the token for a specific registry:
+
+ cargo login --registry my-registry
+
SEE ALSO
cargo(1), cargo-logout(1), cargo-publish(1)
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-logout.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-logout.txt
index db21a39b4..73e50d9a4 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-logout.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-logout.txt
@@ -7,9 +7,16 @@ SYNOPSIS
cargo logout [options]
DESCRIPTION
- This command will remove the API token from the local credential
- storage. Credentials are stored in $CARGO_HOME/credentials.toml where
- $CARGO_HOME defaults to .cargo in your home directory.
+ This command will run a credential provider to remove a saved token.
+
+ For the default cargo:token credential provider, credentials are stored
+ in $CARGO_HOME/credentials.toml where $CARGO_HOME defaults to .cargo in
+ your home directory.
+
+ If a registry has a credential-provider specified, it will be used.
+ Otherwise, the providers from the config value
+ registry.global-credential-providers will be attempted, starting from
+ the end of the list.
If --registry is not specified, then the credentials for the default
registry will be removed (configured by registry.default
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-metadata.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-metadata.txt
index 3d37f6bb8..0d14cfe8e 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-metadata.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-metadata.txt
@@ -22,7 +22,7 @@ OUTPUT FORMAT
Compatibility
Within the same output format version, the compatibility is maintained,
except some scenarios. The following is a non-exhaustive list of changes
- that are not considersed as incompatibile:
+ that are not considersed as incompatible:
o Adding new fields — New fields will be added when needed. Reserving
this helps Cargo evolve without bumping the format version too often.
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-package.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-package.txt
index 1201f3d07..195b35144 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-package.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-package.txt
@@ -197,7 +197,13 @@ OPTIONS
--keep-going
Build as many crates in the dependency graph as possible, rather
than aborting the build on the first one that fails to build.
- Unstable, requires -Zunstable-options.
+
+ For example if the current package depends on dependencies fails and
+ works, one of which fails to build, cargo package -j1 may or may not
+ build the one that succeeds (depending on which one of the two
+ builds Cargo picked to run first), whereas cargo package -j1
+ --keep-going would definitely run both builds, even if the one run
+ first fails.
Display Options
-v, --verbose
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-publish.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-publish.txt
index e8850e3d4..ab1337d3c 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-publish.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-publish.txt
@@ -18,8 +18,12 @@ DESCRIPTION
2. Create a .crate file by following the steps in cargo-package(1).
- 3. Upload the crate to the registry. Note that the server will perform
- additional checks on the crate.
+ 3. Upload the crate to the registry. The server will perform additional
+ checks on the crate.
+
+ 4. The client will poll waiting for the package to appear in the index,
+ and may timeout. In that case, you will need to check for completion
+ manually. This timeout does not affect the upload.
This command requires you to be authenticated with either the --token
option or using cargo-login(1).
@@ -163,7 +167,13 @@ OPTIONS
--keep-going
Build as many crates in the dependency graph as possible, rather
than aborting the build on the first one that fails to build.
- Unstable, requires -Zunstable-options.
+
+ For example if the current package depends on dependencies fails and
+ works, one of which fails to build, cargo publish -j1 may or may not
+ build the one that succeeds (depending on which one of the two
+ builds Cargo picked to run first), whereas cargo publish -j1
+ --keep-going would definitely run both builds, even if the one run
+ first fails.
Display Options
-v, --verbose
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-run.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-run.txt
index 5fcfe66b4..495a08a6c 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-run.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-run.txt
@@ -251,7 +251,13 @@ OPTIONS
--keep-going
Build as many crates in the dependency graph as possible, rather
than aborting the build on the first one that fails to build.
- Unstable, requires -Zunstable-options.
+
+ For example if the current package depends on dependencies fails and
+ works, one of which fails to build, cargo run -j1 may or may not
+ build the one that succeeds (depending on which one of the two
+ builds Cargo picked to run first), whereas cargo run -j1
+ --keep-going would definitely run both builds, even if the one run
+ first fails.
ENVIRONMENT
See the reference
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-rustc.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-rustc.txt
index 7a70c5363..af6ad9d59 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-rustc.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-rustc.txt
@@ -349,7 +349,13 @@ OPTIONS
--keep-going
Build as many crates in the dependency graph as possible, rather
than aborting the build on the first one that fails to build.
- Unstable, requires -Zunstable-options.
+
+ For example if the current package depends on dependencies fails and
+ works, one of which fails to build, cargo rustc -j1 may or may not
+ build the one that succeeds (depending on which one of the two
+ builds Cargo picked to run first), whereas cargo rustc -j1
+ --keep-going would definitely run both builds, even if the one run
+ first fails.
--future-incompat-report
Displays a future-incompat report for any future-incompatible
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-rustdoc.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-rustdoc.txt
index 4db66b3a8..5ba200644 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-rustdoc.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-rustdoc.txt
@@ -319,7 +319,13 @@ OPTIONS
--keep-going
Build as many crates in the dependency graph as possible, rather
than aborting the build on the first one that fails to build.
- Unstable, requires -Zunstable-options.
+
+ For example if the current package depends on dependencies fails and
+ works, one of which fails to build, cargo rustdoc -j1 may or may not
+ build the one that succeeds (depending on which one of the two
+ builds Cargo picked to run first), whereas cargo rustdoc -j1
+ --keep-going would definitely run both builds, even if the one run
+ first fails.
ENVIRONMENT
See the reference
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-test.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-test.txt
index dc32bdbf7..b992d0d2f 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-test.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-test.txt
@@ -448,6 +448,14 @@ OPTIONS
See cargo-report(1)
+ While cargo test involves compilation, it does not provide a
+ --keep-going flag. Use --no-fail-fast to run as many tests as possible
+ without stopping at the first failure. To “compile” as many tests as
+ possible, use --tests to build test binaries separately. For example:
+
+ cargo build --tests --keep-going
+ cargo test --tests --no-fail-fast
+
ENVIRONMENT
See the reference
<https://doc.rust-lang.org/cargo/reference/environment-variables.html>
diff --git a/src/tools/cargo/src/doc/man/generated_txt/cargo-update.txt b/src/tools/cargo/src/doc/man/generated_txt/cargo-update.txt
index fb662c389..a96a34c96 100644
--- a/src/tools/cargo/src/doc/man/generated_txt/cargo-update.txt
+++ b/src/tools/cargo/src/doc/man/generated_txt/cargo-update.txt
@@ -4,7 +4,7 @@ NAME
cargo-update — Update dependencies as recorded in the local lock file
SYNOPSIS
- cargo update [options]
+ cargo update [options] spec
DESCRIPTION
This command will update dependencies in the Cargo.lock file to the
@@ -13,25 +13,25 @@ DESCRIPTION
OPTIONS
Update Options
- -p spec…, --package spec…
+ spec…
Update only the specified packages. This flag may be specified
multiple times. See cargo-pkgid(1) for the SPEC format.
- If packages are specified with the -p flag, then a conservative
- update of the lockfile will be performed. This means that only the
- dependency specified by SPEC will be updated. Its transitive
- dependencies will be updated only if SPEC cannot be updated without
- updating dependencies. All other dependencies will remain locked at
- their currently recorded versions.
+ If packages are specified with spec, then a conservative update of
+ the lockfile will be performed. This means that only the dependency
+ specified by SPEC will be updated. Its transitive dependencies will
+ be updated only if SPEC cannot be updated without updating
+ dependencies. All other dependencies will remain locked at their
+ currently recorded versions.
- If -p is not specified, all dependencies are updated.
+ If spec is not specified, all dependencies are updated.
- --aggressive
- When used with -p, dependencies of spec are forced to update as
+ --recursive
+ When used with spec, dependencies of spec are forced to update as
well. Cannot be used with --precise.
--precise precise
- When used with -p, allows you to specify a specific version number
+ When used with spec, allows you to specify a specific version number
to set the package to. If the package comes from a git repository,
this can be a git revision (such as a SHA hash or tag).
@@ -155,11 +155,11 @@ EXAMPLES
2. Update only specific dependencies:
- cargo update -p foo -p bar
+ cargo update foo bar
3. Set a specific dependency to a specific version:
- cargo update -p foo --precise 1.2.3
+ cargo update foo --precise 1.2.3
SEE ALSO
cargo(1), cargo-generate-lockfile(1)
diff --git a/src/tools/cargo/src/doc/man/includes/options-keep-going.md b/src/tools/cargo/src/doc/man/includes/options-keep-going.md
index 034181c0e..928c7f67a 100644
--- a/src/tools/cargo/src/doc/man/includes/options-keep-going.md
+++ b/src/tools/cargo/src/doc/man/includes/options-keep-going.md
@@ -1,5 +1,10 @@
{{#option "`--keep-going`"}}
Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-`-Zunstable-options`.
+the build on the first one that fails to build.
+
+For example if the current package depends on dependencies `fails` and `works`,
+one of which fails to build, `cargo {{command}} -j1` may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas `cargo {{command}} -j1 --keep-going` would definitely run both
+builds, even if the one run first fails.
{{/option}}
diff --git a/src/tools/cargo/src/doc/src/SUMMARY.md b/src/tools/cargo/src/doc/src/SUMMARY.md
index 273936559..9ebd7915b 100644
--- a/src/tools/cargo/src/doc/src/SUMMARY.md
+++ b/src/tools/cargo/src/doc/src/SUMMARY.md
@@ -36,6 +36,8 @@
* [Source Replacement](reference/source-replacement.md)
* [External Tools](reference/external-tools.md)
* [Registries](reference/registries.md)
+ * [Registry Authentication](reference/registry-authentication.md)
+ * [Credential Provider Protocol](reference/credential-provider-protocol.md)
* [Running a Registry](reference/running-a-registry.md)
* [Registry Index](reference/registry-index.md)
* [Registry Web API](reference/registry-web-api.md)
diff --git a/src/tools/cargo/src/doc/src/appendix/glossary.md b/src/tools/cargo/src/doc/src/appendix/glossary.md
index 143736851..9186b51c3 100644
--- a/src/tools/cargo/src/doc/src/appendix/glossary.md
+++ b/src/tools/cargo/src/doc/src/appendix/glossary.md
@@ -1,25 +1,25 @@
# Glossary
-### Artifact
+## Artifact
An *artifact* is the file or set of files created as a result of the
compilation process. This includes linkable libraries, executable binaries,
and generated documentation.
-### Cargo
+## Cargo
*Cargo* is the Rust [*package manager*](#package-manager), and the primary
topic of this book.
-### Cargo.lock
+## Cargo.lock
See [*lock file*](#lock-file).
-### Cargo.toml
+## Cargo.toml
See [*manifest*](#manifest).
-### Crate
+## Crate
A Rust *crate* is either a library or an executable program, referred to as
either a *library crate* or a *binary crate*, respectively.
@@ -32,14 +32,14 @@ compressed package fetched from a [registry](#registry).
The source code for a given crate may be subdivided into [*modules*](#module).
-### Edition
+## Edition
A *Rust edition* is a developmental landmark of the Rust language. The
[edition of a package][edition-field] is specified in the `Cargo.toml`
[manifest](#manifest), and individual targets can specify which edition they
use. See the [Edition Guide] for more information.
-### Feature
+## Feature
The meaning of *feature* depends on the context:
@@ -58,19 +58,19 @@ The meaning of *feature* depends on the context:
- CPU targets have [*target features*][target-feature] which specify
capabilities of a CPU.
-### Index
+## Index
The *index* is the searchable list of [*crates*](#crate) in a
[*registry*](#registry).
-### Lock file
+## Lock file
The `Cargo.lock` *lock file* is a file that captures the exact version of
every dependency used in a [*workspace*](#workspace) or
[*package*](#package). It is automatically generated by Cargo. See
[Cargo.toml vs Cargo.lock].
-### Manifest
+## Manifest
A [*manifest*][manifest] is a description of a [package](#package) or a
[workspace](#workspace) in a file named `Cargo.toml`.
@@ -78,12 +78,12 @@ A [*manifest*][manifest] is a description of a [package](#package) or a
A [*virtual manifest*][virtual] is a `Cargo.toml` file that only describes a
workspace, and does not include a package.
-### Member
+## Member
A *member* is a [*package*](#package) that belongs to a
[*workspace*](#workspace).
-### Module
+## Module
Rust's module system is used to organize code into logical units called
*modules*, which provide isolated namespaces within the code.
@@ -98,7 +98,7 @@ A [`Cargo.toml`](#manifest) file is primarily concerned with the
which they depend. Nevertheless, you will see the term "module" often when
working with Rust, so you should understand its relationship to a given crate.
-### Package
+## Package
A *package* is a collection of source files and a `Cargo.toml`
[*manifest*](#manifest) file which describes the package. A package has a name
@@ -123,7 +123,7 @@ Larger projects may involve multiple packages, in which case Cargo
[*workspaces*](#workspace) can be used to manage common dependencies and other
related metadata between the packages.
-### Package manager
+## Package manager
Broadly speaking, a *package manager* is a program (or collection of related
programs) in a software ecosystem that automates the process of obtaining,
@@ -139,15 +139,15 @@ downloads your Rust [package](#package)’s dependencies
packages, makes distributable packages, and (optionally) uploads them to
[crates.io][], the Rust community’s [*package registry*](#registry).
-### Package registry
+## Package registry
See [*registry*](#registry).
-### Project
+## Project
Another name for a [package](#package).
-### Registry
+## Registry
A *registry* is a service that contains a collection of downloadable
[*crates*](#crate) that can be installed or used as dependencies for a
@@ -156,7 +156,7 @@ A *registry* is a service that contains a collection of downloadable
contains a list of all crates, and tells Cargo how to download the crates that
are needed.
-### Source
+## Source
A *source* is a provider that contains [*crates*](#crate) that may be included
as dependencies for a [*package*](#package). There are several kinds of
@@ -174,11 +174,11 @@ sources:
See [Source Replacement] for more information.
-### Spec
+## Spec
See [package ID specification](#package).
-### Target
+## Target
The meaning of the term *target* depends on the context:
@@ -216,7 +216,7 @@ The meaning of the term *target* depends on the context:
Some parameters may be omitted. Run `rustc --print target-list` for a list of
supported targets.
-### Test Targets
+## Test Targets
Cargo *test targets* generate binaries which help verify proper operation and
correctness of code. There are two types of test artifacts:
@@ -232,7 +232,7 @@ correctness of code. There are two types of test artifacts:
`Cargo.toml` [*manifest*](#manifest). It is intended to only test the public
API of a library, or execute a binary to verify its operation.
-### Workspace
+## Workspace
A [*workspace*][workspace] is a collection of one or more
[*packages*](#package) that share common dependency resolution (with a shared
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-add.md b/src/tools/cargo/src/doc/src/commands/cargo-add.md
index 132c09326..03485e121 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-add.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-add.md
@@ -1,8 +1,5 @@
# cargo-add(1)
-
-
-
## NAME
cargo-add --- Add dependencies to a Cargo.toml manifest file
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-bench.md b/src/tools/cargo/src/doc/src/commands/cargo-bench.md
index 70ae187a7..45584023e 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-bench.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-bench.md
@@ -1,8 +1,5 @@
# cargo-bench(1)
-
-
-
## NAME
cargo-bench --- Execute benchmarks of a package
@@ -481,13 +478,15 @@ a string <code>default</code> is provided, it sets the value back to defaults.
Should not be 0.</dd>
-<dt class="option-term" id="option-cargo-bench---keep-going"><a class="option-anchor" href="#option-cargo-bench---keep-going"></a><code>--keep-going</code></dt>
-<dd class="option-desc">Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-<code>-Zunstable-options</code>.</dd>
+</dl>
+While `cargo bench` involves compilation, it does not provide a `--keep-going`
+flag. Use `--no-fail-fast` to run as many benchmarks as possible without
+stopping at the first failure. To "compile" as many benchmarks as possible, use
+`--benches` to build benchmark binaries separately. For example:
-</dl>
+ cargo build --benches --release --keep-going
+ cargo bench --no-fail-fast
## ENVIRONMENT
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-build.md b/src/tools/cargo/src/doc/src/commands/cargo-build.md
index 525ab14e5..8e517bd1f 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-build.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-build.md
@@ -1,7 +1,5 @@
# cargo-build(1)
-
-
## NAME
cargo-build --- Compile the current package
@@ -409,8 +407,12 @@ Should not be 0.</dd>
<dt class="option-term" id="option-cargo-build---keep-going"><a class="option-anchor" href="#option-cargo-build---keep-going"></a><code>--keep-going</code></dt>
<dd class="option-desc">Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-<code>-Zunstable-options</code>.</dd>
+the build on the first one that fails to build.</p>
+<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,
+one of which fails to build, <code>cargo build -j1</code> may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas <code>cargo build -j1 --keep-going</code> would definitely run both
+builds, even if the one run first fails.</dd>
<dt class="option-term" id="option-cargo-build---future-incompat-report"><a class="option-anchor" href="#option-cargo-build---future-incompat-report"></a><code>--future-incompat-report</code></dt>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-check.md b/src/tools/cargo/src/doc/src/commands/cargo-check.md
index 4dbc97ad8..3d7d0a490 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-check.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-check.md
@@ -1,7 +1,5 @@
# cargo-check(1)
-
-
## NAME
cargo-check --- Check the current package
@@ -390,8 +388,12 @@ Should not be 0.</dd>
<dt class="option-term" id="option-cargo-check---keep-going"><a class="option-anchor" href="#option-cargo-check---keep-going"></a><code>--keep-going</code></dt>
<dd class="option-desc">Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-<code>-Zunstable-options</code>.</dd>
+the build on the first one that fails to build.</p>
+<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,
+one of which fails to build, <code>cargo check -j1</code> may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas <code>cargo check -j1 --keep-going</code> would definitely run both
+builds, even if the one run first fails.</dd>
<dt class="option-term" id="option-cargo-check---future-incompat-report"><a class="option-anchor" href="#option-cargo-check---future-incompat-report"></a><code>--future-incompat-report</code></dt>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-clean.md b/src/tools/cargo/src/doc/src/commands/cargo-clean.md
index bdbcb86d4..b1415828b 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-clean.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-clean.md
@@ -1,7 +1,5 @@
# cargo-clean(1)
-
-
## NAME
cargo-clean --- Remove generated artifacts
@@ -36,6 +34,11 @@ multiple times. See <a href="cargo-pkgid.html">cargo-pkgid(1)</a> for the SPEC f
<dl>
+<dt class="option-term" id="option-cargo-clean---dry-run"><a class="option-anchor" href="#option-cargo-clean---dry-run"></a><code>--dry-run</code></dt>
+<dd class="option-desc">Displays a summary of what would be deleted without deleting anything.
+Use with <code>--verbose</code> to display the actual files that would be deleted.</dd>
+
+
<dt class="option-term" id="option-cargo-clean---doc"><a class="option-anchor" href="#option-cargo-clean---doc"></a><code>--doc</code></dt>
<dd class="option-desc">This option will cause <code>cargo clean</code> to remove only the <code>doc</code> directory in
the target directory.</dd>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-doc.md b/src/tools/cargo/src/doc/src/commands/cargo-doc.md
index d68bb84e7..92843838c 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-doc.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-doc.md
@@ -1,7 +1,5 @@
# cargo-doc(1)
-
-
## NAME
cargo-doc --- Build a package's documentation
@@ -364,8 +362,12 @@ Should not be 0.</dd>
<dt class="option-term" id="option-cargo-doc---keep-going"><a class="option-anchor" href="#option-cargo-doc---keep-going"></a><code>--keep-going</code></dt>
<dd class="option-desc">Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-<code>-Zunstable-options</code>.</dd>
+the build on the first one that fails to build.</p>
+<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,
+one of which fails to build, <code>cargo doc -j1</code> may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas <code>cargo doc -j1 --keep-going</code> would definitely run both
+builds, even if the one run first fails.</dd>
</dl>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-fetch.md b/src/tools/cargo/src/doc/src/commands/cargo-fetch.md
index e6a460795..54ce48d37 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-fetch.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-fetch.md
@@ -1,8 +1,5 @@
# cargo-fetch(1)
-
-
-
## NAME
cargo-fetch --- Fetch dependencies of a package from the network
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-fix.md b/src/tools/cargo/src/doc/src/commands/cargo-fix.md
index 2bf83fc2e..4dde83d96 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-fix.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-fix.md
@@ -1,7 +1,5 @@
# cargo-fix(1)
-
-
## NAME
cargo-fix --- Automatically fix lint warnings reported by rustc
@@ -470,8 +468,12 @@ Should not be 0.</dd>
<dt class="option-term" id="option-cargo-fix---keep-going"><a class="option-anchor" href="#option-cargo-fix---keep-going"></a><code>--keep-going</code></dt>
<dd class="option-desc">Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-<code>-Zunstable-options</code>.</dd>
+the build on the first one that fails to build.</p>
+<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,
+one of which fails to build, <code>cargo fix -j1</code> may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas <code>cargo fix -j1 --keep-going</code> would definitely run both
+builds, even if the one run first fails.</dd>
</dl>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-install.md b/src/tools/cargo/src/doc/src/commands/cargo-install.md
index af8efcae8..5640af87a 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-install.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-install.md
@@ -1,7 +1,5 @@
# cargo-install(1)
-
-
## NAME
cargo-install --- Build and install a Rust binary
@@ -319,8 +317,12 @@ Should not be 0.</dd>
<dt class="option-term" id="option-cargo-install---keep-going"><a class="option-anchor" href="#option-cargo-install---keep-going"></a><code>--keep-going</code></dt>
<dd class="option-desc">Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-<code>-Zunstable-options</code>.</dd>
+the build on the first one that fails to build.</p>
+<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,
+one of which fails to build, <code>cargo install -j1</code> may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas <code>cargo install -j1 --keep-going</code> would definitely run both
+builds, even if the one run first fails.</dd>
</dl>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-login.md b/src/tools/cargo/src/doc/src/commands/cargo-login.md
index e738dca06..e2efcfe4f 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-login.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-login.md
@@ -2,18 +2,25 @@
## NAME
-cargo-login --- Save an API token from the registry locally
+cargo-login --- Log in to a registry
## SYNOPSIS
-`cargo login` [_options_] [_token_]
+`cargo login` [_options_] [_token_] -- [_args_]
## DESCRIPTION
-This command will save the API token to disk so that commands that require
-authentication, such as [cargo-publish(1)](cargo-publish.html), will be automatically
-authenticated. The token is saved in `$CARGO_HOME/credentials.toml`. `CARGO_HOME`
-defaults to `.cargo` in your home directory.
+This command will run a credential provider to save a token so that commands
+that require authentication, such as [cargo-publish(1)](cargo-publish.html), will be
+automatically authenticated.
+
+For the default `cargo:token` credential provider, the token is saved
+in `$CARGO_HOME/credentials.toml`. `CARGO_HOME` defaults to `.cargo`
+in your home directory.
+
+If a registry has a credential-provider specified, it will be used. Otherwise,
+the providers from the config value `registry.global-credential-providers` will
+be attempted, starting from the end of the list.
If the _token_ argument is not specified, it will be read from stdin.
@@ -122,9 +129,13 @@ details on environment variables that Cargo reads.
## EXAMPLES
-1. Save the API token to disk:
+1. Save the token for the default registry:
cargo login
+2. Save the token for a specific registry:
+
+ cargo login --registry my-registry
+
## SEE ALSO
[cargo(1)](cargo.html), [cargo-logout(1)](cargo-logout.html), [cargo-publish(1)](cargo-publish.html)
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-logout.md b/src/tools/cargo/src/doc/src/commands/cargo-logout.md
index 16e393b02..3cc50f6e9 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-logout.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-logout.md
@@ -10,9 +10,15 @@ cargo-logout --- Remove an API token from the registry locally
## DESCRIPTION
-This command will remove the API token from the local credential storage.
-Credentials are stored in `$CARGO_HOME/credentials.toml` where `$CARGO_HOME`
-defaults to `.cargo` in your home directory.
+This command will run a credential provider to remove a saved token.
+
+For the default `cargo:token` credential provider, credentials are stored
+in `$CARGO_HOME/credentials.toml` where `$CARGO_HOME` defaults to `.cargo`
+in your home directory.
+
+If a registry has a credential-provider specified, it will be used. Otherwise,
+the providers from the config value `registry.global-credential-providers` will
+be attempted, starting from the end of the list.
If `--registry` is not specified, then the credentials for the default
registry will be removed (configured by
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-metadata.md b/src/tools/cargo/src/doc/src/commands/cargo-metadata.md
index 5be6992d7..24b68d283 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-metadata.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-metadata.md
@@ -27,7 +27,7 @@ for a Rust API for reading the metadata.
Within the same output format version, the compatibility is maintained, except
some scenarios. The following is a non-exhaustive list of changes that are not
-considersed as incompatibile:
+considersed as incompatible:
* **Adding new fields** — New fields will be added when needed. Reserving this
helps Cargo evolve without bumping the format version too often.
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-package.md b/src/tools/cargo/src/doc/src/commands/cargo-package.md
index f9c7c552d..12684aa3c 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-package.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-package.md
@@ -1,8 +1,5 @@
# cargo-package(1)
-
-
-
## NAME
cargo-package --- Assemble the local package into a distributable tarball
@@ -234,8 +231,12 @@ Should not be 0.</dd>
<dt class="option-term" id="option-cargo-package---keep-going"><a class="option-anchor" href="#option-cargo-package---keep-going"></a><code>--keep-going</code></dt>
<dd class="option-desc">Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-<code>-Zunstable-options</code>.</dd>
+the build on the first one that fails to build.</p>
+<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,
+one of which fails to build, <code>cargo package -j1</code> may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas <code>cargo package -j1 --keep-going</code> would definitely run both
+builds, even if the one run first fails.</dd>
</dl>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-publish.md b/src/tools/cargo/src/doc/src/commands/cargo-publish.md
index fe37d9f97..bc84e61c0 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-publish.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-publish.md
@@ -1,7 +1,5 @@
# cargo-publish(1)
-
-
## NAME
cargo-publish --- Upload a package to the registry
@@ -21,8 +19,11 @@ following steps:
- Checks the `package.publish` key in the manifest for restrictions on
which registries you are allowed to publish to.
2. Create a `.crate` file by following the steps in [cargo-package(1)](cargo-package.html).
-3. Upload the crate to the registry. Note that the server will perform
- additional checks on the crate.
+3. Upload the crate to the registry. The server will perform additional
+ checks on the crate.
+4. The client will poll waiting for the package to appear in the index,
+ and may timeout. In that case, you will need to check for completion
+ manually. This timeout does not affect the upload.
This command requires you to be authenticated with either the `--token` option
or using [cargo-login(1)](cargo-login.html).
@@ -200,8 +201,12 @@ Should not be 0.</dd>
<dt class="option-term" id="option-cargo-publish---keep-going"><a class="option-anchor" href="#option-cargo-publish---keep-going"></a><code>--keep-going</code></dt>
<dd class="option-desc">Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-<code>-Zunstable-options</code>.</dd>
+the build on the first one that fails to build.</p>
+<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,
+one of which fails to build, <code>cargo publish -j1</code> may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas <code>cargo publish -j1 --keep-going</code> would definitely run both
+builds, even if the one run first fails.</dd>
</dl>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-remove.md b/src/tools/cargo/src/doc/src/commands/cargo-remove.md
index 571c41075..9e97b533a 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-remove.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-remove.md
@@ -1,7 +1,5 @@
# cargo-remove(1)
-
-
## NAME
cargo-remove --- Remove dependencies from a Cargo.toml manifest file
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-run.md b/src/tools/cargo/src/doc/src/commands/cargo-run.md
index bd3e4724a..c14ad77dc 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-run.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-run.md
@@ -1,6 +1,5 @@
# cargo-run(1)
-
## NAME
cargo-run --- Run the current package
@@ -306,8 +305,12 @@ Should not be 0.</dd>
<dt class="option-term" id="option-cargo-run---keep-going"><a class="option-anchor" href="#option-cargo-run---keep-going"></a><code>--keep-going</code></dt>
<dd class="option-desc">Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-<code>-Zunstable-options</code>.</dd>
+the build on the first one that fails to build.</p>
+<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,
+one of which fails to build, <code>cargo run -j1</code> may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas <code>cargo run -j1 --keep-going</code> would definitely run both
+builds, even if the one run first fails.</dd>
</dl>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-rustc.md b/src/tools/cargo/src/doc/src/commands/cargo-rustc.md
index 2147d617c..6ae52d965 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-rustc.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-rustc.md
@@ -1,7 +1,5 @@
# cargo-rustc(1)
-
-
## NAME
cargo-rustc --- Compile the current package, and pass extra options to the compiler
@@ -403,8 +401,12 @@ Should not be 0.</dd>
<dt class="option-term" id="option-cargo-rustc---keep-going"><a class="option-anchor" href="#option-cargo-rustc---keep-going"></a><code>--keep-going</code></dt>
<dd class="option-desc">Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-<code>-Zunstable-options</code>.</dd>
+the build on the first one that fails to build.</p>
+<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,
+one of which fails to build, <code>cargo rustc -j1</code> may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas <code>cargo rustc -j1 --keep-going</code> would definitely run both
+builds, even if the one run first fails.</dd>
<dt class="option-term" id="option-cargo-rustc---future-incompat-report"><a class="option-anchor" href="#option-cargo-rustc---future-incompat-report"></a><code>--future-incompat-report</code></dt>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-rustdoc.md b/src/tools/cargo/src/doc/src/commands/cargo-rustdoc.md
index 22c1c8322..6635cded5 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-rustdoc.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-rustdoc.md
@@ -1,7 +1,5 @@
# cargo-rustdoc(1)
-
-
## NAME
cargo-rustdoc --- Build a package's documentation, using specified custom flags
@@ -383,8 +381,12 @@ Should not be 0.</dd>
<dt class="option-term" id="option-cargo-rustdoc---keep-going"><a class="option-anchor" href="#option-cargo-rustdoc---keep-going"></a><code>--keep-going</code></dt>
<dd class="option-desc">Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-<code>-Zunstable-options</code>.</dd>
+the build on the first one that fails to build.</p>
+<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,
+one of which fails to build, <code>cargo rustdoc -j1</code> may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas <code>cargo rustdoc -j1 --keep-going</code> would definitely run both
+builds, even if the one run first fails.</dd>
</dl>
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-test.md b/src/tools/cargo/src/doc/src/commands/cargo-test.md
index bcf46d601..6a6ae82d2 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-test.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-test.md
@@ -1,8 +1,5 @@
# cargo-test(1)
-
-
-
## NAME
cargo-test --- Execute unit and integration tests of a package
@@ -524,6 +521,14 @@ produced during execution of this command</p>
</dl>
+While `cargo test` involves compilation, it does not provide a `--keep-going`
+flag. Use `--no-fail-fast` to run as many tests as possible without stopping at
+the first failure. To "compile" as many tests as possible, use `--tests` to
+build test binaries separately. For example:
+
+ cargo build --tests --keep-going
+ cargo test --tests --no-fail-fast
+
## ENVIRONMENT
See [the reference](../reference/environment-variables.html) for
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-tree.md b/src/tools/cargo/src/doc/src/commands/cargo-tree.md
index 9a9aa9f0c..948c3581c 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-tree.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-tree.md
@@ -1,7 +1,5 @@
# cargo-tree(1)
-
-
## NAME
cargo-tree --- Display a tree visualization of a dependency graph
diff --git a/src/tools/cargo/src/doc/src/commands/cargo-update.md b/src/tools/cargo/src/doc/src/commands/cargo-update.md
index 3cfd69282..234998faa 100644
--- a/src/tools/cargo/src/doc/src/commands/cargo-update.md
+++ b/src/tools/cargo/src/doc/src/commands/cargo-update.md
@@ -6,7 +6,7 @@ cargo-update --- Update dependencies as recorded in the local lock file
## SYNOPSIS
-`cargo update` [_options_]
+`cargo update` [_options_] _spec_
## DESCRIPTION
@@ -20,25 +20,24 @@ latest available versions.
<dl>
-<dt class="option-term" id="option-cargo-update--p"><a class="option-anchor" href="#option-cargo-update--p"></a><code>-p</code> <em>spec</em>…</dt>
-<dt class="option-term" id="option-cargo-update---package"><a class="option-anchor" href="#option-cargo-update---package"></a><code>--package</code> <em>spec</em>…</dt>
+<dt class="option-term" id="option-cargo-update-spec…"><a class="option-anchor" href="#option-cargo-update-spec…"></a><em>spec</em>…</dt>
<dd class="option-desc">Update only the specified packages. This flag may be specified
multiple times. See <a href="cargo-pkgid.html">cargo-pkgid(1)</a> for the SPEC format.</p>
-<p>If packages are specified with the <code>-p</code> flag, then a conservative update of
+<p>If packages are specified with <em>spec</em>, then a conservative update of
the lockfile will be performed. This means that only the dependency specified
by SPEC will be updated. Its transitive dependencies will be updated only if
SPEC cannot be updated without updating dependencies. All other dependencies
will remain locked at their currently recorded versions.</p>
-<p>If <code>-p</code> is not specified, all dependencies are updated.</dd>
+<p>If <em>spec</em> is not specified, all dependencies are updated.</dd>
-<dt class="option-term" id="option-cargo-update---aggressive"><a class="option-anchor" href="#option-cargo-update---aggressive"></a><code>--aggressive</code></dt>
-<dd class="option-desc">When used with <code>-p</code>, dependencies of <em>spec</em> are forced to update as well.
+<dt class="option-term" id="option-cargo-update---recursive"><a class="option-anchor" href="#option-cargo-update---recursive"></a><code>--recursive</code></dt>
+<dd class="option-desc">When used with <em>spec</em>, dependencies of <em>spec</em> are forced to update as well.
Cannot be used with <code>--precise</code>.</dd>
<dt class="option-term" id="option-cargo-update---precise"><a class="option-anchor" href="#option-cargo-update---precise"></a><code>--precise</code> <em>precise</em></dt>
-<dd class="option-desc">When used with <code>-p</code>, allows you to specify a specific version number to set
+<dd class="option-desc">When used with <em>spec</em>, allows you to specify a specific version number to set
the package to. If the package comes from a git repository, this can be a git
revision (such as a SHA hash or tag).</dd>
@@ -187,11 +186,11 @@ details on environment variables that Cargo reads.
2. Update only specific dependencies:
- cargo update -p foo -p bar
+ cargo update foo bar
3. Set a specific dependency to a specific version:
- cargo update -p foo --precise 1.2.3
+ cargo update foo --precise 1.2.3
## SEE ALSO
[cargo(1)](cargo.html), [cargo-generate-lockfile(1)](cargo-generate-lockfile.html)
diff --git a/src/tools/cargo/src/doc/src/faq.md b/src/tools/cargo/src/doc/src/faq.md
index e4a753413..9d4a982d0 100644
--- a/src/tools/cargo/src/doc/src/faq.md
+++ b/src/tools/cargo/src/doc/src/faq.md
@@ -1,6 +1,6 @@
-## Frequently Asked Questions
+# Frequently Asked Questions
-### Is the plan to use GitHub as a package repository?
+## Is the plan to use GitHub as a package repository?
No. The plan for Cargo is to use [crates.io], like npm or Rubygems do with
[npmjs.com][1] and [rubygems.org][3].
@@ -9,7 +9,7 @@ We plan to support git repositories as a source of packages forever,
because they can be used for early development and temporary patches,
even when people use the registry as the primary source of packages.
-### Why build crates.io rather than use GitHub as a registry?
+## Why build crates.io rather than use GitHub as a registry?
We think that it’s very important to support multiple ways to download
packages, including downloading from GitHub and copying packages into
@@ -43,7 +43,7 @@ languages include:
down fast. Also remember that not everybody has a high-speed,
low-latency Internet connection.
-### Will Cargo work with C code (or other languages)?
+## Will Cargo work with C code (or other languages)?
Yes!
@@ -56,7 +56,7 @@ Our solution: Cargo allows a package to [specify a script](reference/build-scrip
implement platform-specific configuration and refactor out common build
functionality among packages.
-### Can Cargo be used inside of `make` (or `ninja`, or ...)
+## Can Cargo be used inside of `make` (or `ninja`, or ...)
Indeed. While we intend Cargo to be useful as a standalone way to
compile Rust packages at the top-level, we know that some people will
@@ -68,7 +68,7 @@ have some work to do on those fronts, but using Cargo in the context of
conventional scripts is something we designed for from the beginning and
will continue to prioritize.
-### Does Cargo handle multi-platform packages or cross-compilation?
+## Does Cargo handle multi-platform packages or cross-compilation?
Rust itself provides facilities for configuring sections of code based
on the platform. Cargo also supports [platform-specific
@@ -80,7 +80,7 @@ configuration in `Cargo.toml` in the future.
In the longer-term, we’re looking at ways to conveniently cross-compile
packages using Cargo.
-### Does Cargo support environments, like `production` or `test`?
+## Does Cargo support environments, like `production` or `test`?
We support environments through the use of [profiles] to support:
@@ -92,7 +92,7 @@ We support environments through the use of [profiles] to support:
* environment-specific `#[cfg]`
* a `cargo test` command
-### Does Cargo work on Windows?
+## Does Cargo work on Windows?
Yes!
@@ -102,35 +102,49 @@ issue][cargo-issues].
[cargo-issues]: https://github.com/rust-lang/cargo/issues
-### Why do binaries have `Cargo.lock` in version control, but not libraries?
+## Why have `Cargo.lock` in version control?
-The purpose of a `Cargo.lock` lockfile is to describe the state of the world at
-the time of a successful build. Cargo uses the lockfile to provide
-deterministic builds on different times and different systems, by ensuring that
-the exact same dependencies and versions are used as when the `Cargo.lock` file
-was originally generated.
-
-This property is most desirable from applications and packages which are at the
-very end of the dependency chain (binaries). As a result, it is recommended that
-all binaries check in their `Cargo.lock`.
-
-For libraries the situation is somewhat different. A library is not only used by
-the library developers, but also any downstream consumers of the library. Users
-dependent on the library will not inspect the library’s `Cargo.lock` (even if it
-exists). This is precisely because a library should **not** be deterministically
-recompiled for all users of the library.
+While [`cargo new`] defaults to tracking `Cargo.lock` in version control,
+whether you do is dependent on the needs of your package.
-If a library ends up being used transitively by several dependencies, it’s
-likely that just a single copy of the library is desired (based on semver
-compatibility). If Cargo used all of the dependencies' `Cargo.lock` files,
-then multiple copies of the library could be used, and perhaps even a version
-conflict.
-
-In other words, libraries specify SemVer requirements for their dependencies but
-cannot see the full picture. Only end products like binaries have a full
-picture to decide what versions of dependencies should be used.
-
-### Can libraries use `*` as a version for their dependencies?
+The purpose of a `Cargo.lock` lockfile is to describe the state of the world at
+the time of a successful build.
+Cargo uses the lockfile to provide deterministic builds at different times and
+on different systems,
+by ensuring that the exact same dependencies and versions are used as when the
+`Cargo.lock` file was originally generated.
+
+Deterministic builds help with
+- Running `git bisect` to find the root cause of a bug
+- Ensuring CI only fails due to new commits and not external factors
+- Reducing confusion when contributors see different behavior as compared to
+ other contributors or CI
+
+Having this snapshot of dependencies can also help when projects need to be
+verified against consistent versions of dependencies, like when
+- Verifying a minimum-supported Rust version (MSRV) that is less than the latest
+ version of a dependency supports
+- Verifying human readable output which won't have compatibility guarantees
+ (e.g. snapshot testing error messages to ensure they are "understandable", a
+ metric too fuzzy to automate)
+
+However, this determinism can give a false sense of security because
+`Cargo.lock` does not affect the consumers of your package, only `Cargo.toml` does that.
+For example:
+- [`cargo install`] will select the latest dependencies unless `--locked` is
+ passed in.
+- New dependencies, like those added with [`cargo add`], will be locked to the latest version
+
+The lockfile can also be a source of merge conflicts.
+
+For strategies to verify newer versions of dependencies via CI,
+see [Verifying Latest Dependencies](guide/continuous-integration.md#verifying-latest-dependencies).
+
+[`cargo new`]: commands/cargo-new.md
+[`cargo add`]: commands/cargo-add.md
+[`cargo install`]: commands/cargo-install.md
+
+## Can libraries use `*` as a version for their dependencies?
**As of January 22nd, 2016, [crates.io] rejects all packages (not just libraries)
with wildcard dependency constraints.**
@@ -140,7 +154,7 @@ of `*` says “This will work with every version ever”, which is never going
to be true. Libraries should always specify the range that they do work with,
even if it’s something as general as “every 1.x.y version”.
-### Why `Cargo.toml`?
+## Why `Cargo.toml`?
As one of the most frequent interactions with Cargo, the question of why the
configuration file is named `Cargo.toml` arises from time to time. The leading
@@ -158,7 +172,7 @@ but others were accidentally forgotten.
[crates.io]: https://crates.io/
-### How can Cargo work offline?
+## How can Cargo work offline?
Cargo is often used in situations with limited or no network access such as
airplanes, CI environments, or embedded in large production deployments. Users
@@ -202,7 +216,7 @@ replacement][replace].
[`cargo fetch`]: commands/cargo-fetch.md
[offline config]: reference/config.md#netoffline
-### Why is Cargo rebuilding my code?
+## Why is Cargo rebuilding my code?
Cargo is responsible for incrementally compiling crates in your project. This
means that if you type `cargo build` twice the second one shouldn't rebuild your
@@ -260,7 +274,7 @@ If after trying to debug your issue, however, you're still running into problems
then feel free to [open an
issue](https://github.com/rust-lang/cargo/issues/new)!
-### What does "version conflict" mean and how to resolve it?
+## What does "version conflict" mean and how to resolve it?
> failed to select a version for `x` which could resolve this conflict
diff --git a/src/tools/cargo/src/doc/src/getting-started/first-steps.md b/src/tools/cargo/src/doc/src/getting-started/first-steps.md
index 15bb4bdc7..e8ed21d15 100644
--- a/src/tools/cargo/src/doc/src/getting-started/first-steps.md
+++ b/src/tools/cargo/src/doc/src/getting-started/first-steps.md
@@ -1,4 +1,4 @@
-## First Steps with Cargo
+# First Steps with Cargo
This section provides a quick sense for the `cargo` command line tool. We
demonstrate its ability to generate a new [***package***][def-package] for us,
@@ -73,7 +73,7 @@ $ cargo run
Hello, world!
```
-### Going further
+## Going further
For more details on using Cargo, check out the [Cargo Guide](../guide/index.md)
diff --git a/src/tools/cargo/src/doc/src/getting-started/index.md b/src/tools/cargo/src/doc/src/getting-started/index.md
index 710e9943b..30eca72ef 100644
--- a/src/tools/cargo/src/doc/src/getting-started/index.md
+++ b/src/tools/cargo/src/doc/src/getting-started/index.md
@@ -1,4 +1,4 @@
-## Getting Started
+# Getting Started
To get started with Cargo, install Cargo (and Rust) and set up your first
[*crate*][def-crate].
diff --git a/src/tools/cargo/src/doc/src/getting-started/installation.md b/src/tools/cargo/src/doc/src/getting-started/installation.md
index 7cccf9ee5..21ba2fd4c 100644
--- a/src/tools/cargo/src/doc/src/getting-started/installation.md
+++ b/src/tools/cargo/src/doc/src/getting-started/installation.md
@@ -1,6 +1,6 @@
-## Installation
+# Installation
-### Install Rust and Cargo
+## Install Rust and Cargo
The easiest way to get Cargo is to install the current stable release of [Rust]
by using [rustup]. Installing Rust using `rustup` will also install `cargo`.
@@ -27,7 +27,7 @@ channels for Rust and Cargo.
For other installation options and information, visit the
[install][install-rust] page of the Rust website.
-### Build and Install Cargo from Source
+## Build and Install Cargo from Source
Alternatively, you can [build Cargo from source][compiling-from-source].
diff --git a/src/tools/cargo/src/doc/src/guide/build-cache.md b/src/tools/cargo/src/doc/src/guide/build-cache.md
index a79b41dba..d351fc158 100644
--- a/src/tools/cargo/src/doc/src/guide/build-cache.md
+++ b/src/tools/cargo/src/doc/src/guide/build-cache.md
@@ -1,4 +1,4 @@
-## Build cache
+# Build cache
Cargo stores the output of a build into the "target" directory. By default,
this is the directory named `target` in the root of your
@@ -63,7 +63,7 @@ Directory | Description
<code style="white-space: nowrap">target/debug/incremental/</code> | `rustc` [incremental output], a cache used to speed up subsequent builds.
<code style="white-space: nowrap">target/debug/build/</code> | Output from [build scripts].
-### Dep-info files
+## Dep-info files
Next to each compiled artifact is a file called a "dep info" file with a `.d`
suffix. This file is a Makefile-like syntax that indicates all of the file
@@ -77,7 +77,7 @@ re-executed. The paths in the file are absolute by default. See the
/path/to/myproj/target/debug/foo: /path/to/myproj/src/lib.rs /path/to/myproj/src/main.rs
```
-### Shared cache
+## Shared cache
A third party tool, [sccache], can be used to share built dependencies across
different workspaces.
diff --git a/src/tools/cargo/src/doc/src/guide/cargo-home.md b/src/tools/cargo/src/doc/src/guide/cargo-home.md
index 9e6740f10..33e3f00a1 100644
--- a/src/tools/cargo/src/doc/src/guide/cargo-home.md
+++ b/src/tools/cargo/src/doc/src/guide/cargo-home.md
@@ -1,4 +1,4 @@
-## Cargo Home
+# Cargo Home
The "Cargo home" functions as a download and source cache.
When building a [crate][def-crate], Cargo stores downloaded build dependencies in the Cargo home.
diff --git a/src/tools/cargo/src/doc/src/guide/cargo-toml-vs-cargo-lock.md b/src/tools/cargo/src/doc/src/guide/cargo-toml-vs-cargo-lock.md
index 84d697f66..21f52dca1 100644
--- a/src/tools/cargo/src/doc/src/guide/cargo-toml-vs-cargo-lock.md
+++ b/src/tools/cargo/src/doc/src/guide/cargo-toml-vs-cargo-lock.md
@@ -1,4 +1,4 @@
-## Cargo.toml vs Cargo.lock
+# Cargo.toml vs Cargo.lock
`Cargo.toml` and `Cargo.lock` serve two different purposes. Before we talk
about them, here’s a summary:
@@ -8,14 +8,11 @@ about them, here’s a summary:
* `Cargo.lock` contains exact information about your dependencies. It is
maintained by Cargo and should not be manually edited.
-If you’re building a non-end product, such as a rust library that other rust
-[packages][def-package] will depend on, put `Cargo.lock` in your
-`.gitignore`. If you’re building an end product, which are executable like
-command-line tool or an application, or a system library with crate-type of
-`staticlib` or `cdylib`, check `Cargo.lock` into `git`. If you're curious
-about why that is, see
-["Why do binaries have `Cargo.lock` in version control, but not libraries?" in the
-FAQ](../faq.md#why-do-binaries-have-cargolock-in-version-control-but-not-libraries).
+When in doubt, check `Cargo.lock` into the version control system (e.g. Git).
+For a better understanding of why and what the alternatives might be, see
+[“Why have Cargo.lock in version control?” in the FAQ](../faq.md#why-have-cargolock-in-version-control).
+We recommend pairing this with
+[Verifying Latest Dependencies](continuous-integration.md#verifying-latest-dependencies)
Let’s dig in a little bit more.
@@ -94,8 +91,8 @@ When we’re ready to opt in to a new version of the library, Cargo can
re-calculate the dependencies and update things for us:
```console
-$ cargo update # updates all dependencies
-$ cargo update -p regex # updates just “regex”
+$ cargo update # updates all dependencies
+$ cargo update regex # updates just “regex”
```
This will write out a new `Cargo.lock` with the new version information. Note
diff --git a/src/tools/cargo/src/doc/src/guide/continuous-integration.md b/src/tools/cargo/src/doc/src/guide/continuous-integration.md
index 38d8ae20e..0c3cec889 100644
--- a/src/tools/cargo/src/doc/src/guide/continuous-integration.md
+++ b/src/tools/cargo/src/doc/src/guide/continuous-integration.md
@@ -1,25 +1,8 @@
-## Continuous Integration
+# Continuous Integration
-### Travis CI
+## Getting Started
-To test your [package][def-package] on Travis CI, here is a sample
-`.travis.yml` file:
-
-```yaml
-language: rust
-rust:
- - stable
- - beta
- - nightly
-matrix:
- allow_failures:
- - rust: nightly
-```
-
-This will test all three release channels, but any breakage in nightly
-will not fail your overall build. Please see the [Travis CI Rust
-documentation](https://docs.travis-ci.com/user/languages/rust/) for more
-information.
+A basic CI will build and test your projects:
### GitHub Actions
@@ -122,4 +105,58 @@ channel, but any breakage in nightly will not fail your overall build. Please
see the [builds.sr.ht documentation](https://man.sr.ht/builds.sr.ht/) for more
information.
-[def-package]: ../appendix/glossary.md#package '"package" (glossary entry)'
+## Verifying Latest Dependencies
+
+When [specifying dependencies](../reference/specifying-dependencies.md) in
+`Cargo.toml`, they generally match a range of versions.
+Exhaustively testing all version combination would be unwieldy.
+Verifying the latest versions would at least test for users who run [`cargo
+add`] or [`cargo install`].
+
+When testing the latest versions some considerations are:
+- Minimizing external factors affecting local development or CI
+- Rate of new dependencies being published
+- Level of risk a project is willing to accept
+- CI costs, including indirect costs like if a CI service has a maximum for
+ parallel runners, causing new jobs to be serialized when at the maximum.
+
+Some potential solutions include:
+- [Not checking in the `Cargo.lock`](../faq.md#why-have-cargolock-in-version-control)
+ - Depending on PR velocity, many versions may go untested
+ - This comes at the cost of determinism
+- Have a CI job verify the latest dependencies but mark it to "continue on failure"
+ - Depending on the CI service, failures might not be obvious
+ - Depending on PR velocity, may use more resources than necessary
+- Have a scheduled CI job to verify latest dependencies
+ - A hosted CI service may disable scheduled jobs for repositories that
+ haven't been touched in a while, affecting passively maintained packages
+ - Depending on the CI service, notifications might not be routed to people
+ who can act on the failure
+ - If not balanced with dependency publish rate, may not test enough versions
+ or may do redundant testing
+- Regularly update dependencies through PRs, like with [Dependabot] or [RenovateBot]
+ - Can isolate dependencies to their own PR or roll them up into a single PR
+ - Only uses the resources necessary
+ - Can configure the frequency to balance CI resources and coverage of dependency versions
+
+An example CI job to verify latest dependencies, using GitHub Actions:
+```yaml
+jobs:
+ latest_deps:
+ name: Latest Dependencies
+ runs-on: ubuntu-latest
+ continue-on-error: true
+ steps:
+ - uses: actions/checkout@v3
+ - run: rustup update stable && rustup default stable
+ - run: cargo update --verbose
+ - run: cargo build --verbose
+ - run: cargo test --verbose
+```
+For projects with higher risks of per-platform or per-Rust version failures,
+more combinations may want to be tested.
+
+[`cargo add`]: ../commands/cargo-add.md
+[`cargo install`]: ../commands/cargo-install.md
+[Dependabot]: https://docs.github.com/en/code-security/dependabot/working-with-dependabot
+[RenovateBot]: https://renovatebot.com/
diff --git a/src/tools/cargo/src/doc/src/guide/creating-a-new-project.md b/src/tools/cargo/src/doc/src/guide/creating-a-new-project.md
index e0daefc6b..49fbc0880 100644
--- a/src/tools/cargo/src/doc/src/guide/creating-a-new-project.md
+++ b/src/tools/cargo/src/doc/src/guide/creating-a-new-project.md
@@ -1,4 +1,4 @@
-## Creating a New Package
+# Creating a New Package
To start a new [package][def-package] with Cargo, use `cargo new`:
diff --git a/src/tools/cargo/src/doc/src/guide/dependencies.md b/src/tools/cargo/src/doc/src/guide/dependencies.md
index 94419f15b..cbb3ba115 100644
--- a/src/tools/cargo/src/doc/src/guide/dependencies.md
+++ b/src/tools/cargo/src/doc/src/guide/dependencies.md
@@ -1,4 +1,4 @@
-## Dependencies
+# Dependencies
[crates.io] is the Rust community's central [*package registry*][def-package-registry]
that serves as a location to discover and download
@@ -9,7 +9,7 @@ To depend on a library hosted on [crates.io], add it to your `Cargo.toml`.
[crates.io]: https://crates.io/
-### Adding a dependency
+## Adding a dependency
If your `Cargo.toml` doesn't already have a `[dependencies]` section, add
that, then list the [crate][def-crate] name and version that you would like to
diff --git a/src/tools/cargo/src/doc/src/guide/index.md b/src/tools/cargo/src/doc/src/guide/index.md
index fe6d86a39..00fe2320c 100644
--- a/src/tools/cargo/src/doc/src/guide/index.md
+++ b/src/tools/cargo/src/doc/src/guide/index.md
@@ -1,4 +1,4 @@
-## Cargo Guide
+# Cargo Guide
This guide will give you all that you need to know about how to use Cargo to
develop Rust packages.
diff --git a/src/tools/cargo/src/doc/src/guide/project-layout.md b/src/tools/cargo/src/doc/src/guide/project-layout.md
index a3ce3f8a7..c4360af01 100644
--- a/src/tools/cargo/src/doc/src/guide/project-layout.md
+++ b/src/tools/cargo/src/doc/src/guide/project-layout.md
@@ -1,4 +1,4 @@
-## Package Layout
+# Package Layout
Cargo uses conventions for file placement to make it easy to dive into a new
Cargo [package][def-package]:
diff --git a/src/tools/cargo/src/doc/src/guide/tests.md b/src/tools/cargo/src/doc/src/guide/tests.md
index 402e8e35c..0148c9120 100644
--- a/src/tools/cargo/src/doc/src/guide/tests.md
+++ b/src/tools/cargo/src/doc/src/guide/tests.md
@@ -1,4 +1,4 @@
-## Tests
+# Tests
Cargo can run your tests with the `cargo test` command. Cargo looks for tests
to run in two places: in each of your `src` files and any tests in `tests/`.
diff --git a/src/tools/cargo/src/doc/src/guide/why-cargo-exists.md b/src/tools/cargo/src/doc/src/guide/why-cargo-exists.md
index 02b222f01..2081944f7 100644
--- a/src/tools/cargo/src/doc/src/guide/why-cargo-exists.md
+++ b/src/tools/cargo/src/doc/src/guide/why-cargo-exists.md
@@ -1,6 +1,6 @@
-## Why Cargo Exists
+# Why Cargo Exists
-### Preliminaries
+## Preliminaries
In Rust, as you may know, a library or executable program is called a
[*crate*][def-crate]. Crates are compiled using the Rust compiler,
@@ -31,7 +31,7 @@ involved with performing the above tasks by introducing a higher-level
["*package*"][def-package] abstraction and by using a
[*package manager*][def-package-manager].
-### Enter: Cargo
+## Enter: Cargo
*Cargo* is the Rust package manager. It is a tool that allows Rust
[*packages*][def-package] to declare their various dependencies and ensure
diff --git a/src/tools/cargo/src/doc/src/guide/working-on-an-existing-project.md b/src/tools/cargo/src/doc/src/guide/working-on-an-existing-project.md
index f9c26cd90..446248530 100644
--- a/src/tools/cargo/src/doc/src/guide/working-on-an-existing-project.md
+++ b/src/tools/cargo/src/doc/src/guide/working-on-an-existing-project.md
@@ -1,4 +1,4 @@
-## Working on an Existing Cargo Package
+# Working on an Existing Cargo Package
If you download an existing [package][def-package] that uses Cargo, it’s
really easy to get going.
diff --git a/src/tools/cargo/src/doc/src/index.md b/src/tools/cargo/src/doc/src/index.md
index 223600c8b..a7b01c60b 100644
--- a/src/tools/cargo/src/doc/src/index.md
+++ b/src/tools/cargo/src/doc/src/index.md
@@ -7,8 +7,7 @@ dependencies, compiles your packages, makes distributable packages, and uploads
[crates.io], the Rust community’s [*package registry*][def-package-registry]. You can contribute
to this book on [GitHub].
-
-### Sections
+## Sections
**[Getting Started](getting-started/index.md)**
diff --git a/src/tools/cargo/src/doc/src/reference/build-script-examples.md b/src/tools/cargo/src/doc/src/reference/build-script-examples.md
index 5e8fae5bb..e55d4704d 100644
--- a/src/tools/cargo/src/doc/src/reference/build-script-examples.md
+++ b/src/tools/cargo/src/doc/src/reference/build-script-examples.md
@@ -1,4 +1,4 @@
-## Build Script Examples
+# Build Script Examples
The following sections illustrate some examples of writing build scripts.
@@ -22,7 +22,7 @@ available. The following is a sample of some popular crates[^†]:
[^†]: This list is not an endorsement. Evaluate your dependencies to see which
is right for your project.
-### Code generation
+## Code generation
Some Cargo packages need to have code generated just before they are compiled
for various reasons. Here we’ll walk through a simple example which generates a
@@ -120,7 +120,7 @@ from the build script itself.
[concat-macro]: ../../std/macro.concat.html
[env-macro]: ../../std/macro.env.html
-### Building a native library
+## Building a native library
Sometimes it’s necessary to build some native C or C++ code as part of a
package. This is another excellent use case of leveraging the build script to
@@ -268,7 +268,7 @@ dependency purely for the build process and not for the crate itself at runtime.
[`cc` crate]: https://crates.io/crates/cc
-### Linking to system libraries
+## Linking to system libraries
This example demonstrates how to link a system library and how the build
script is used to support this use case.
@@ -363,7 +363,7 @@ source][libz-source] for a more complete example.
[`pkg-config` crate]: https://crates.io/crates/pkg-config
[libz-source]: https://github.com/rust-lang/libz-sys
-### Using another `sys` crate
+## Using another `sys` crate
When using the `links` key, crates may set metadata that can be read by other
crates that depend on it. This provides a mechanism to communicate information
@@ -424,7 +424,7 @@ already installed.
// … rest of code that makes use of zlib.
```
-### Conditional compilation
+## Conditional compilation
A build script may emit [`rustc-cfg` instructions] which can enable conditions
that can be checked at compile time. In this example, we'll take a look at how
diff --git a/src/tools/cargo/src/doc/src/reference/build-scripts.md b/src/tools/cargo/src/doc/src/reference/build-scripts.md
index e7560812b..451850388 100644
--- a/src/tools/cargo/src/doc/src/reference/build-scripts.md
+++ b/src/tools/cargo/src/doc/src/reference/build-scripts.md
@@ -1,4 +1,4 @@
-## Build Scripts
+# Build Scripts
Some packages need to compile third-party non-Rust code, for example C
libraries. Other packages need to link to C libraries which can either be
@@ -37,7 +37,7 @@ scripts.
> Note: The [`package.build` manifest key](manifest.md#the-build-field) can be
> used to change the name of the build script, or disable it entirely.
-### Life Cycle of a Build Script
+## Life Cycle of a Build Script
Just before a package is built, Cargo will compile a build script into an
executable (if it has not already been built). It will then run the script,
@@ -57,7 +57,7 @@ will be compiled. Scripts should exit with a non-zero exit code to halt the
build if there is an error, in which case the build script's output will be
displayed on the terminal.
-### Inputs to the Build Script
+## Inputs to the Build Script
When the build script is run, there are a number of inputs to the build script,
all passed in the form of [environment variables][build-env].
@@ -67,7 +67,7 @@ the source directory of the build script’s package.
[build-env]: environment-variables.md#environment-variables-cargo-sets-for-build-scripts
-### Outputs of the Build Script
+## Outputs of the Build Script
Build scripts may save any output files or intermediate artifacts in the
directory specified in the [`OUT_DIR` environment variable][build-env]. Scripts
@@ -132,7 +132,7 @@ one detailed below.
scripts.
-#### `cargo:rustc-link-arg=FLAG` {#rustc-link-arg}
+### `cargo:rustc-link-arg=FLAG` {#rustc-link-arg}
The `rustc-link-arg` instruction tells Cargo to pass the [`-C link-arg=FLAG`
option][link-arg] to the compiler, but only when building supported targets
@@ -142,7 +142,7 @@ linker script.
[link-arg]: ../../rustc/codegen-options/index.md#link-arg
-#### `cargo:rustc-link-arg-bin=BIN=FLAG` {#rustc-link-arg-bin}
+### `cargo:rustc-link-arg-bin=BIN=FLAG` {#rustc-link-arg-bin}
The `rustc-link-arg-bin` instruction tells Cargo to pass the [`-C
link-arg=FLAG` option][link-arg] to the compiler, but only when building
@@ -150,7 +150,7 @@ the binary target with name `BIN`. Its usage is highly platform specific. It is
to set a linker script or other linker options.
-#### `cargo:rustc-link-arg-bins=FLAG` {#rustc-link-arg-bins}
+### `cargo:rustc-link-arg-bins=FLAG` {#rustc-link-arg-bins}
The `rustc-link-arg-bins` instruction tells Cargo to pass the [`-C
link-arg=FLAG` option][link-arg] to the compiler, but only when building a
@@ -158,7 +158,7 @@ binary target. Its usage is highly platform specific. It is useful
to set a linker script or other linker options.
-#### `cargo:rustc-link-lib=LIB` {#rustc-link-lib}
+### `cargo:rustc-link-lib=LIB` {#rustc-link-lib}
The `rustc-link-lib` instruction tells Cargo to link the given library using
the compiler's [`-l` flag][option-link]. This is typically used to link a
@@ -183,26 +183,26 @@ The optional `KIND` may be one of `dylib`, `static`, or `framework`. See the
[FFI]: ../../nomicon/ffi.md
-#### `cargo:rustc-link-arg-tests=FLAG` {#rustc-link-arg-tests}
+### `cargo:rustc-link-arg-tests=FLAG` {#rustc-link-arg-tests}
The `rustc-link-arg-tests` instruction tells Cargo to pass the [`-C
link-arg=FLAG` option][link-arg] to the compiler, but only when building a
tests target.
-#### `cargo:rustc-link-arg-examples=FLAG` {#rustc-link-arg-examples}
+### `cargo:rustc-link-arg-examples=FLAG` {#rustc-link-arg-examples}
The `rustc-link-arg-examples` instruction tells Cargo to pass the [`-C
link-arg=FLAG` option][link-arg] to the compiler, but only when building an examples
target.
-#### `cargo:rustc-link-arg-benches=FLAG` {#rustc-link-arg-benches}
+### `cargo:rustc-link-arg-benches=FLAG` {#rustc-link-arg-benches}
The `rustc-link-arg-benches` instruction tells Cargo to pass the [`-C
link-arg=FLAG` option][link-arg] to the compiler, but only when building a benchmark
target.
-#### `cargo:rustc-link-search=[KIND=]PATH` {#rustc-link-search}
+### `cargo:rustc-link-search=[KIND=]PATH` {#rustc-link-search}
The `rustc-link-search` instruction tells Cargo to pass the [`-L`
flag][option-search] to the compiler to add a directory to the library search
@@ -220,14 +220,14 @@ is fine).
[option-search]: ../../rustc/command-line-arguments.md#option-l-search-path
-#### `cargo:rustc-flags=FLAGS` {#rustc-flags}
+### `cargo:rustc-flags=FLAGS` {#rustc-flags}
The `rustc-flags` instruction tells Cargo to pass the given space-separated
flags to the compiler. This only allows the `-l` and `-L` flags, and is
equivalent to using [`rustc-link-lib`](#rustc-link-lib) and
[`rustc-link-search`](#rustc-link-search).
-#### `cargo:rustc-cfg=KEY[="VALUE"]` {#rustc-cfg}
+### `cargo:rustc-cfg=KEY[="VALUE"]` {#rustc-cfg}
The `rustc-cfg` instruction tells Cargo to pass the given value to the
[`--cfg` flag][option-cfg] to the compiler. This may be used for compile-time
@@ -248,7 +248,7 @@ identifier, the value should be a string.
[conditional compilation]: ../../reference/conditional-compilation.md
[option-cfg]: ../../rustc/command-line-arguments.md#option-cfg
-#### `cargo:rustc-env=VAR=VALUE` {#rustc-env}
+### `cargo:rustc-env=VAR=VALUE` {#rustc-env}
The `rustc-env` instruction tells Cargo to set the given environment variable
when compiling the package. The value can be then retrieved by the [`env!`
@@ -268,7 +268,7 @@ Cargo][env-cargo].
[env-macro]: ../../std/macro.env.html
[env-cargo]: environment-variables.md#environment-variables-cargo-sets-for-crates
-#### `cargo:rustc-cdylib-link-arg=FLAG` {#rustc-cdylib-link-arg}
+### `cargo:rustc-cdylib-link-arg=FLAG` {#rustc-cdylib-link-arg}
The `rustc-cdylib-link-arg` instruction tells Cargo to pass the [`-C
link-arg=FLAG` option][link-arg] to the compiler, but only when building a
@@ -276,7 +276,7 @@ link-arg=FLAG` option][link-arg] to the compiler, but only when building a
to set the shared library version or the runtime-path.
-#### `cargo:warning=MESSAGE` {#cargo-warning}
+### `cargo:warning=MESSAGE` {#cargo-warning}
The `warning` instruction tells Cargo to display a warning after the build
script has finished running. Warnings are only shown for `path` dependencies
@@ -284,7 +284,7 @@ script has finished running. Warnings are only shown for `path` dependencies
out in [crates.io] crates are not emitted by default. The `-vv` "very verbose"
flag may be used to have Cargo display warnings for all crates.
-### Build Dependencies
+## Build Dependencies
Build scripts are also allowed to have dependencies on other Cargo-based crates.
Dependencies are declared through the `build-dependencies` section of the
@@ -306,7 +306,7 @@ attempt to reuse a dependency if it is shared between build dependencies and
normal dependencies. However, this is not always possible, for example when
cross-compiling, so keep that in consideration of the impact on compile time.
-### Change Detection
+## Change Detection
When rebuilding a package, Cargo does not necessarily know if the build script
needs to be run again. By default, it takes a conservative approach of always
@@ -321,7 +321,7 @@ FAQ](../faq.md#why-is-cargo-rebuilding-my-code).
[`exclude` and `include` fields]: manifest.md#the-exclude-and-include-fields
-#### `cargo:rerun-if-changed=PATH` {#rerun-if-changed}
+### `cargo:rerun-if-changed=PATH` {#rerun-if-changed}
The `rerun-if-changed` instruction tells Cargo to re-run the build script if
the file at the given path has changed. Currently, Cargo only uses the
@@ -340,7 +340,7 @@ automatically handles whether or not the script itself needs to be recompiled,
and of course the script will be re-run after it has been recompiled.
Otherwise, specifying `build.rs` is redundant and unnecessary.
-#### `cargo:rerun-if-env-changed=NAME` {#rerun-if-env-changed}
+### `cargo:rerun-if-env-changed=NAME` {#rerun-if-env-changed}
The `rerun-if-env-changed` instruction tells Cargo to re-run the build script
if the value of an environment variable of the given name has changed.
@@ -352,7 +352,7 @@ environment variables in use are those received by `cargo` invocations, not
those received by the executable of the build script.
-### The `links` Manifest Key
+## The `links` Manifest Key
The `package.links` key may be set in the `Cargo.toml` manifest to declare
that the package links with the given native library. The purpose of this
@@ -390,7 +390,7 @@ dependents.
[using-another-sys]: build-script-examples.md#using-another-sys-crate
-### `*-sys` Packages
+## `*-sys` Packages
Some Cargo packages that link to system libraries have a naming convention of
having a `-sys` suffix. Any package named `foo-sys` should provide two major
@@ -423,7 +423,7 @@ example, the [`git2` crate] provides a high-level interface to the
[`git2` crate]: https://crates.io/crates/git2
[`libgit2-sys` crate]: https://crates.io/crates/libgit2-sys
-### Overriding Build Scripts
+## Overriding Build Scripts
If a manifest contains a `links` key, then Cargo supports overriding the build
script specified with a custom library. The purpose of this functionality is to
@@ -451,7 +451,7 @@ be used instead.
The `warning`, `rerun-if-changed`, and `rerun-if-env-changed` keys should not
be used and will be ignored.
-### Jobserver
+## Jobserver
Cargo and `rustc` use the [jobserver protocol], developed for GNU make, to
coordinate concurrency across processes. It is essentially a semaphore that
diff --git a/src/tools/cargo/src/doc/src/reference/cargo-targets.md b/src/tools/cargo/src/doc/src/reference/cargo-targets.md
index 7aea15109..ef29a520f 100644
--- a/src/tools/cargo/src/doc/src/reference/cargo-targets.md
+++ b/src/tools/cargo/src/doc/src/reference/cargo-targets.md
@@ -1,4 +1,4 @@
-## Cargo Targets
+# Cargo Targets
Cargo packages consist of *targets* which correspond to source files which can
be compiled into a crate. Packages can have [library](#library),
@@ -10,7 +10,7 @@ by the [directory layout][package layout] of the source files.
See [Configuring a target](#configuring-a-target) below for details on
configuring the settings for a target.
-### Library
+## Library
The library target defines a "library" that can be used and linked by other
libraries and executables. The filename defaults to `src/lib.rs`, and the name
@@ -25,7 +25,7 @@ crate-type = ["cdylib"]
bench = false
```
-### Binaries
+## Binaries
Binary targets are executable programs that can be run after being compiled.
The default binary filename is `src/main.rs`, which defaults to the name of
@@ -52,7 +52,7 @@ name = "frobnicator"
required-features = ["frobnicate"]
```
-### Examples
+## Examples
Files located under the [`examples` directory][package layout] are example
uses of the functionality provided by the library. When compiled, they are
@@ -81,7 +81,7 @@ default to protect them from bit-rotting. Set [the `test`
field](#the-test-field) to `true` if you have `#[test]` functions in the
example that you want to run with [`cargo test`].
-### Tests
+## Tests
There are two styles of tests within a Cargo project:
@@ -108,7 +108,7 @@ strategy.
[libtest harness]: ../../rustc/tests/index.html
[cargo-test-documentation-tests]: ../commands/cargo-test.md#documentation-tests
-#### Integration tests
+### Integration tests
Files located under the [`tests` directory][package layout] are integration
tests. When you run [`cargo test`], Cargo will compile each of these files as
@@ -140,7 +140,7 @@ executable.
[environment variable]: environment-variables.md#environment-variables-cargo-sets-for-crates
[`env` macro]: ../../std/macro.env.html
-### Benchmarks
+## Benchmarks
Benchmarks provide a way to test the performance of your code using the
[`cargo bench`] command. They follow the same structure as [tests](#tests),
@@ -163,7 +163,7 @@ Similarly to tests:
> may help with running benchmarks on the stable channel, such as
> [Criterion](https://crates.io/crates/criterion).
-### Configuring a target
+## Configuring a target
All of the `[lib]`, `[[bin]]`, `[[example]]`, `[[test]]`, and `[[bench]]`
sections in `Cargo.toml` support similar configuration for specifying how a
@@ -192,7 +192,7 @@ crate-type = ["lib"] # The crate types to generate.
required-features = [] # Features required to build this target (N/A for lib).
```
-#### The `name` field
+### The `name` field
The `name` field specifies the name of the target, which corresponds to the
filename of the artifact that will be generated. For a library, this is the
@@ -205,7 +205,7 @@ directory or file name.
This is required for all targets except `[lib]`.
-#### The `path` field
+### The `path` field
The `path` field specifies where the source for the crate is located, relative
to the `Cargo.toml` file.
@@ -213,7 +213,7 @@ to the `Cargo.toml` file.
If not specified, the [inferred path](#target-auto-discovery) is used based on
the target name.
-#### The `test` field
+### The `test` field
The `test` field indicates whether or not the target is tested by default by
[`cargo test`]. The default is `true` for lib, bins, and tests.
@@ -223,19 +223,19 @@ The `test` field indicates whether or not the target is tested by default by
> true` for an example will also build it as a test and run any
> [`#[test]`][test-attribute] functions defined in the example.
-#### The `doctest` field
+### The `doctest` field
The `doctest` field indicates whether or not [documentation examples] are
tested by default by [`cargo test`]. This is only relevant for libraries, it
has no effect on other sections. The default is `true` for the library.
-#### The `bench` field
+### The `bench` field
The `bench` field indicates whether or not the target is benchmarked by
default by [`cargo bench`]. The default is `true` for lib, bins, and
benchmarks.
-#### The `doc` field
+### The `doc` field
The `doc` field indicates whether or not the target is included in the
documentation generated by [`cargo doc`] by default. The default is `true` for
@@ -244,17 +244,17 @@ libraries and binaries.
> **Note**: The binary will be skipped if its name is the same as the lib
> target.
-#### The `plugin` field
+### The `plugin` field
This field is used for `rustc` plugins, which are being deprecated.
-#### The `proc-macro` field
+### The `proc-macro` field
The `proc-macro` field indicates that the library is a [procedural macro]
([reference][proc-macro-reference]). This is only valid for the `[lib]`
target.
-#### The `harness` field
+### The `harness` field
The `harness` field indicates that the [`--test` flag] will be passed to
`rustc` which will automatically include the libtest library which is the
@@ -268,7 +268,7 @@ to run tests and benchmarks.
Tests have the [`cfg(test)` conditional expression][cfg-test] enabled whether
or not the harness is enabled.
-#### The `edition` field
+### The `edition` field
The `edition` field defines the [Rust edition] the target will use. If not
specified, it defaults to the [`edition` field][package-edition] for the
@@ -276,7 +276,7 @@ specified, it defaults to the [`edition` field][package-edition] for the
advanced scenarios such as incrementally transitioning a large package to a
new edition.
-#### The `crate-type` field
+### The `crate-type` field
The `crate-type` field defines the [crate types] that will be generated by the
target. It is an array of strings, allowing you to specify multiple crate
@@ -294,7 +294,7 @@ The available options are `bin`, `lib`, `rlib`, `dylib`, `cdylib`,
`staticlib`, and `proc-macro`. You can read more about the different crate
types in the [Rust Reference Manual][crate types].
-#### The `required-features` field
+### The `required-features` field
The `required-features` field specifies which [features] the target needs in
order to be built. If any of the required features are not enabled, the
@@ -314,7 +314,7 @@ required-features = ["postgres", "tools"]
```
-### Target auto-discovery
+## Target auto-discovery
By default, Cargo automatically determines the targets to build based on the
[layout of the files][package layout] on the filesystem. The target
diff --git a/src/tools/cargo/src/doc/src/reference/config.md b/src/tools/cargo/src/doc/src/reference/config.md
index d1f2b04d3..6a479b81b 100644
--- a/src/tools/cargo/src/doc/src/reference/config.md
+++ b/src/tools/cargo/src/doc/src/reference/config.md
@@ -1,10 +1,10 @@
-## Configuration
+# Configuration
This document explains how Cargo’s configuration system works, as well as
available keys or configuration. For configuration of a package through its
manifest, see the [manifest format](manifest.md).
-### Hierarchical structure
+## Hierarchical structure
Cargo allows local configuration for a particular package as well as global
configuration. It looks for configuration files in the current directory and
@@ -28,7 +28,8 @@ with a configuration file in your home directory.
If a key is specified in multiple config files, the values will get merged
together. Numbers, strings, and booleans will use the value in the deeper
config directory taking precedence over ancestor directories, where the
-home directory is the lowest priority. Arrays will be joined together.
+home directory is the lowest priority. Arrays will be joined together
+with higher precedence items being placed later in the merged array.
At present, when being invoked from a workspace, Cargo does not read config
files from crates within the workspace. i.e. if a workspace has two crates in
@@ -43,7 +44,7 @@ those configuration files if it is invoked from the workspace root
> and is the preferred form. If both files exist, Cargo will use the file
> without the extension.
-### Configuration format
+## Configuration format
Configuration files are written in the [TOML format][toml] (like the
manifest), with simple key-value pairs inside of sections (tables). The
@@ -183,7 +184,7 @@ progress.when = 'auto' # whether cargo shows progress bar
progress.width = 80 # width of progress bar
```
-### Environment variables
+## Environment variables
Cargo can also be configured through environment variables in addition to the
TOML configuration files. For each configuration key of the form `foo.bar` the
@@ -202,7 +203,7 @@ supported due to [technical issues](https://github.com/rust-lang/cargo/issues/54
In addition to the system above, Cargo recognizes a few other specific
[environment variables][env].
-### Command-line overrides
+## Command-line overrides
Cargo also accepts arbitrary configuration overrides through the
`--config` command-line option. The argument should be in TOML syntax of
@@ -242,7 +243,7 @@ configuration files that Cargo should use for a specific invocation.
Options from configuration files loaded this way follow the same
precedence rules as other options specified directly with `--config`.
-### Config-relative paths
+## Config-relative paths
Paths in config files may be absolute, relative, or a bare name without any path separators.
Paths for executables without a path separator will use the `PATH` environment variable to search for the executable.
@@ -279,7 +280,7 @@ runner = "foo" # Searches `PATH` for `foo`.
directory = "vendor"
```
-### Executable paths with arguments
+## Executable paths with arguments
Some Cargo commands invoke external programs, which can be configured as a path
and some number of arguments.
@@ -293,11 +294,13 @@ run, they will be passed after the last specified argument in the value of an
option of this format. If the specified program does not have path separators,
Cargo will search `PATH` for its executable.
-### Credentials
+## Credentials
Configuration values with sensitive information are stored in the
`$CARGO_HOME/credentials.toml` file. This file is automatically created and updated
-by [`cargo login`] and [`cargo logout`]. It follows the same format as Cargo config files.
+by [`cargo login`] and [`cargo logout`] when using the `cargo:token` credential provider.
+
+It follows the same format as Cargo config files.
```toml
[registry]
@@ -324,14 +327,14 @@ all capital letters.
> extension by default. However, for backward compatibility reason, when both
> files exist, Cargo will read and write the file without the extension.
-### Configuration keys
+## Configuration keys
This section documents all configuration keys. The description for keys with
variable parts are annotated with angled brackets like `target.<triple>` where
the `<triple>` part can be any [target triple] like
`target.x86_64-pc-windows-msvc`.
-#### `paths`
+### `paths`
* Type: array of strings (paths)
* Default: none
* Environment: not supported
@@ -340,7 +343,7 @@ An array of paths to local packages which are to be used as overrides for
dependencies. For more information see the [Overriding Dependencies
guide](overriding-dependencies.md#paths-overrides).
-#### `[alias]`
+### `[alias]`
* Type: string or array of strings
* Default: see below
* Environment: `CARGO_ALIAS_<name>`
@@ -372,11 +375,11 @@ rr = "run --release"
recursive_example = "rr --example recursions"
```
-#### `[build]`
+### `[build]`
The `[build]` table controls build-time operations and compiler settings.
-##### `build.jobs`
+#### `build.jobs`
* Type: integer or string
* Default: number of logical CPUs
* Environment: `CARGO_BUILD_JOBS`
@@ -388,14 +391,14 @@ the value back to defaults.
Can be overridden with the `--jobs` CLI option.
-##### `build.rustc`
+#### `build.rustc`
* Type: string (program path)
* Default: "rustc"
* Environment: `CARGO_BUILD_RUSTC` or `RUSTC`
Sets the executable to use for `rustc`.
-##### `build.rustc-wrapper`
+#### `build.rustc-wrapper`
* Type: string (program path)
* Default: none
* Environment: `CARGO_BUILD_RUSTC_WRAPPER` or `RUSTC_WRAPPER`
@@ -404,7 +407,7 @@ Sets a wrapper to execute instead of `rustc`. The first argument passed to the
wrapper is the path to the actual executable to use
(i.e., `build.rustc`, if that is set, or `"rustc"` otherwise).
-##### `build.rustc-workspace-wrapper`
+#### `build.rustc-workspace-wrapper`
* Type: string (program path)
* Default: none
* Environment: `CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER` or `RUSTC_WORKSPACE_WRAPPER`
@@ -414,14 +417,14 @@ The first argument passed to the wrapper is the path to the actual
executable to use (i.e., `build.rustc`, if that is set, or `"rustc"` otherwise).
It affects the filename hash so that artifacts produced by the wrapper are cached separately.
-##### `build.rustdoc`
+#### `build.rustdoc`
* Type: string (program path)
* Default: "rustdoc"
* Environment: `CARGO_BUILD_RUSTDOC` or `RUSTDOC`
Sets the executable to use for `rustdoc`.
-##### `build.target`
+#### `build.target`
* Type: string or array of strings
* Default: host platform
* Environment: `CARGO_BUILD_TARGET`
@@ -441,7 +444,7 @@ Can be overridden with the `--target` CLI option.
target = ["x86_64-unknown-linux-gnu", "i686-unknown-linux-gnu"]
```
-##### `build.target-dir`
+#### `build.target-dir`
* Type: string (path)
* Default: "target"
* Environment: `CARGO_BUILD_TARGET_DIR` or `CARGO_TARGET_DIR`
@@ -451,7 +454,7 @@ is a directory named `target` located at the root of the workspace.
Can be overridden with the `--target-dir` CLI option.
-##### `build.rustflags`
+#### `build.rustflags`
* Type: string or array of strings
* Default: none
* Environment: `CARGO_BUILD_RUSTFLAGS` or `CARGO_ENCODED_RUSTFLAGS` or `RUSTFLAGS`
@@ -488,7 +491,7 @@ appropriate profile setting.
> flags you specify. This is an area where Cargo may not always be backwards
> compatible.
-##### `build.rustdocflags`
+#### `build.rustdocflags`
* Type: string or array of strings
* Default: none
* Environment: `CARGO_BUILD_RUSTDOCFLAGS` or `CARGO_ENCODED_RUSTDOCFLAGS` or `RUSTDOCFLAGS`
@@ -505,7 +508,7 @@ order, with the first one being used:
Additional flags may also be passed with the [`cargo rustdoc`] command.
-##### `build.incremental`
+#### `build.incremental`
* Type: bool
* Default: from profile
* Environment: `CARGO_BUILD_INCREMENTAL` or `CARGO_INCREMENTAL`
@@ -518,7 +521,7 @@ The `CARGO_INCREMENTAL` environment variable can be set to `1` to force enable
incremental compilation for all profiles, or `0` to disable it. This env var
overrides the config setting.
-##### `build.dep-info-basedir`
+#### `build.dep-info-basedir`
* Type: string (path)
* Default: none
* Environment: `CARGO_BUILD_DEP_INFO_BASEDIR`
@@ -532,15 +535,35 @@ The setting itself is a config-relative path. So, for example, a value of
`"."` would strip all paths starting with the parent directory of the `.cargo`
directory.
-##### `build.pipelining`
+#### `build.pipelining`
This option is deprecated and unused. Cargo always has pipelining enabled.
-#### `[doc]`
+### `[credential-alias]`
+* Type: string or array of strings
+* Default: empty
+* Environment: `CARGO_CREDENTIAL_ALIAS_<name>`
+
+The `[credential-alias]` table defines credential provider aliases.
+These aliases can be referenced as an element of the `registry.global-credential-providers`
+array, or as a credential provider for a specific registry
+under `registries.<NAME>.credential-provider`.
+
+If specified as a string, the value will be split on spaces into path and arguments.
+
+For example, to define an alias called `my-alias`:
+
+```toml
+[credential-alias]
+my-alias = ["/usr/bin/cargo-credential-example", "--argument", "value", "--flag"]
+```
+See [Registry Authentication](registry-authentication.md) for more information.
+
+### `[doc]`
The `[doc]` table defines options for the [`cargo doc`] command.
-##### `doc.browser`
+#### `doc.browser`
* Type: string or array of strings ([program path with args])
* Default: `BROWSER` environment variable, or, if that is missing,
@@ -550,19 +573,19 @@ This option sets the browser to be used by [`cargo doc`], overriding the
`BROWSER` environment variable when opening documentation with the `--open`
option.
-#### `[cargo-new]`
+### `[cargo-new]`
The `[cargo-new]` table defines defaults for the [`cargo new`] command.
-##### `cargo-new.name`
+#### `cargo-new.name`
This option is deprecated and unused.
-##### `cargo-new.email`
+#### `cargo-new.email`
This option is deprecated and unused.
-##### `cargo-new.vcs`
+#### `cargo-new.vcs`
* Type: string
* Default: "git" or "none"
* Environment: `CARGO_CARGO_NEW_VCS`
@@ -610,25 +633,25 @@ Controls how often we display a notification to the terminal when a future incom
* `always` (default): Always display a notification when a command (e.g. `cargo build`) produces a future incompat report
* `never`: Never display a notification
-#### `[http]`
+### `[http]`
The `[http]` table defines settings for HTTP behavior. This includes fetching
crate dependencies and accessing remote git repositories.
-##### `http.debug`
+#### `http.debug`
* Type: boolean
* Default: false
* Environment: `CARGO_HTTP_DEBUG`
If `true`, enables debugging of HTTP requests. The debug information can be
-seen by setting the `CARGO_LOG=cargo::ops::registry=debug` environment
-variable (or use `trace` for even more information).
+seen by setting the `CARGO_LOG=network=debug` environment
+variable (or use `network=trace` for even more information).
Be wary when posting logs from this output in a public location. The output
may include headers with authentication tokens which you don't want to leak!
Be sure to review logs before posting them.
-##### `http.proxy`
+#### `http.proxy`
* Type: string
* Default: none
* Environment: `CARGO_HTTP_PROXY` or `HTTPS_PROXY` or `https_proxy` or `http_proxy`
@@ -639,14 +662,14 @@ setting in your global git configuration. If none of those are set, the
`HTTPS_PROXY` or `https_proxy` environment variables set the proxy for HTTPS
requests, and `http_proxy` sets it for HTTP requests.
-##### `http.timeout`
+#### `http.timeout`
* Type: integer
* Default: 30
* Environment: `CARGO_HTTP_TIMEOUT` or `HTTP_TIMEOUT`
Sets the timeout for each HTTP request, in seconds.
-##### `http.cainfo`
+#### `http.cainfo`
* Type: string (path)
* Default: none
* Environment: `CARGO_HTTP_CAINFO`
@@ -654,7 +677,7 @@ Sets the timeout for each HTTP request, in seconds.
Path to a Certificate Authority (CA) bundle file, used to verify TLS
certificates. If not specified, Cargo attempts to use the system certificates.
-##### `http.check-revoke`
+#### `http.check-revoke`
* Type: boolean
* Default: true (Windows) false (all others)
* Environment: `CARGO_HTTP_CHECK_REVOKE`
@@ -662,7 +685,7 @@ certificates. If not specified, Cargo attempts to use the system certificates.
This determines whether or not TLS certificate revocation checks should be
performed. This only works on Windows.
-##### `http.ssl-version`
+#### `http.ssl-version`
* Type: string or min/max table
* Default: none
* Environment: `CARGO_HTTP_SSL_VERSION`
@@ -678,7 +701,7 @@ range of TLS versions to use.
The default is a minimum version of "tlsv1.0" and a max of the newest version
supported on your platform, typically "tlsv1.3".
-##### `http.low-speed-limit`
+#### `http.low-speed-limit`
* Type: integer
* Default: 10
* Environment: `CARGO_HTTP_LOW_SPEED_LIMIT`
@@ -688,7 +711,7 @@ transfer speed in bytes per second is below the given value for
[`http.timeout`](#httptimeout) seconds (default 30 seconds), then the
connection is considered too slow and Cargo will abort and retry.
-##### `http.multiplexing`
+#### `http.multiplexing`
* Type: boolean
* Default: true
* Environment: `CARGO_HTTP_MULTIPLEXING`
@@ -698,7 +721,7 @@ This allows multiple requests to use the same connection, usually improving
performance when fetching multiple files. If `false`, Cargo will use HTTP 1.1
without pipelining.
-##### `http.user-agent`
+#### `http.user-agent`
* Type: string
* Default: Cargo's version
* Environment: `CARGO_HTTP_USER_AGENT`
@@ -706,11 +729,11 @@ without pipelining.
Specifies a custom user-agent header to use. The default if not specified is a
string that includes Cargo's version.
-#### `[install]`
+### `[install]`
The `[install]` table defines defaults for the [`cargo install`] command.
-##### `install.root`
+#### `install.root`
* Type: string (path)
* Default: Cargo's home directory
* Environment: `CARGO_INSTALL_ROOT`
@@ -726,18 +749,18 @@ your home directory).
Can be overridden with the `--root` command-line option.
-#### `[net]`
+### `[net]`
The `[net]` table controls networking configuration.
-##### `net.retry`
+#### `net.retry`
* Type: integer
* Default: 3
* Environment: `CARGO_NET_RETRY`
Number of times to retry possibly spurious network errors.
-##### `net.git-fetch-with-cli`
+#### `net.git-fetch-with-cli`
* Type: boolean
* Default: false
* Environment: `CARGO_NET_GIT_FETCH_WITH_CLI`
@@ -751,7 +774,7 @@ requirements that Cargo does not support. See [Git
Authentication](../appendix/git-authentication.md) for more information about
setting up git authentication.
-##### `net.offline`
+#### `net.offline`
* Type: boolean
* Default: false
* Environment: `CARGO_NET_OFFLINE`
@@ -762,11 +785,11 @@ needed, and generate an error if it encounters a network error.
Can be overridden with the `--offline` command-line option.
-##### `net.ssh`
+#### `net.ssh`
The `[net.ssh]` table contains settings for SSH connections.
-##### `net.ssh.known-hosts`
+#### `net.ssh.known-hosts`
* Type: array of strings
* Default: see description
* Environment: not supported
@@ -797,7 +820,7 @@ for more details.
[github-keys]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints
-#### `[patch]`
+### `[patch]`
Just as you can override dependencies using [`[patch]` in
`Cargo.toml`](overriding-dependencies.md#the-patch-section), you can
@@ -822,7 +845,7 @@ lowest precedence.
Relative `path` dependencies in such a `[patch]` section are resolved
relative to the configuration file they appear in.
-#### `[profile]`
+### `[profile]`
The `[profile]` table can be used to globally change profile settings, and
override settings specified in `Cargo.toml`. It has the same syntax and
@@ -831,91 +854,91 @@ details about the options.
[Profiles chapter]: profiles.md
-##### `[profile.<name>.build-override]`
+#### `[profile.<name>.build-override]`
* Environment: `CARGO_PROFILE_<name>_BUILD_OVERRIDE_<key>`
The build-override table overrides settings for build scripts, proc macros,
and their dependencies. It has the same keys as a normal profile. See the
[overrides section](profiles.md#overrides) for more details.
-##### `[profile.<name>.package.<name>]`
+#### `[profile.<name>.package.<name>]`
* Environment: not supported
The package table overrides settings for specific packages. It has the same
keys as a normal profile, minus the `panic`, `lto`, and `rpath` settings. See
the [overrides section](profiles.md#overrides) for more details.
-##### `profile.<name>.codegen-units`
+#### `profile.<name>.codegen-units`
* Type: integer
* Default: See profile docs.
* Environment: `CARGO_PROFILE_<name>_CODEGEN_UNITS`
See [codegen-units](profiles.md#codegen-units).
-##### `profile.<name>.debug`
+#### `profile.<name>.debug`
* Type: integer or boolean
* Default: See profile docs.
* Environment: `CARGO_PROFILE_<name>_DEBUG`
See [debug](profiles.md#debug).
-##### `profile.<name>.split-debuginfo`
+#### `profile.<name>.split-debuginfo`
* Type: string
* Default: See profile docs.
* Environment: `CARGO_PROFILE_<name>_SPLIT_DEBUGINFO`
See [split-debuginfo](profiles.md#split-debuginfo).
-##### `profile.<name>.debug-assertions`
+#### `profile.<name>.debug-assertions`
* Type: boolean
* Default: See profile docs.
* Environment: `CARGO_PROFILE_<name>_DEBUG_ASSERTIONS`
See [debug-assertions](profiles.md#debug-assertions).
-##### `profile.<name>.incremental`
+#### `profile.<name>.incremental`
* Type: boolean
* Default: See profile docs.
* Environment: `CARGO_PROFILE_<name>_INCREMENTAL`
See [incremental](profiles.md#incremental).
-##### `profile.<name>.lto`
+#### `profile.<name>.lto`
* Type: string or boolean
* Default: See profile docs.
* Environment: `CARGO_PROFILE_<name>_LTO`
See [lto](profiles.md#lto).
-##### `profile.<name>.overflow-checks`
+#### `profile.<name>.overflow-checks`
* Type: boolean
* Default: See profile docs.
* Environment: `CARGO_PROFILE_<name>_OVERFLOW_CHECKS`
See [overflow-checks](profiles.md#overflow-checks).
-##### `profile.<name>.opt-level`
+#### `profile.<name>.opt-level`
* Type: integer or string
* Default: See profile docs.
* Environment: `CARGO_PROFILE_<name>_OPT_LEVEL`
See [opt-level](profiles.md#opt-level).
-##### `profile.<name>.panic`
+#### `profile.<name>.panic`
* Type: string
* default: See profile docs.
* Environment: `CARGO_PROFILE_<name>_PANIC`
See [panic](profiles.md#panic).
-##### `profile.<name>.rpath`
+#### `profile.<name>.rpath`
* Type: boolean
* default: See profile docs.
* Environment: `CARGO_PROFILE_<name>_RPATH`
See [rpath](profiles.md#rpath).
-##### `profile.<name>.strip`
+#### `profile.<name>.strip`
* Type: string
* default: See profile docs.
* Environment: `CARGO_PROFILE_<name>_STRIP`
@@ -923,19 +946,19 @@ See [rpath](profiles.md#rpath).
See [strip](profiles.md#strip).
-#### `[registries]`
+### `[registries]`
The `[registries]` table is used for specifying additional [registries]. It
consists of a sub-table for each named registry.
-##### `registries.<name>.index`
+#### `registries.<name>.index`
* Type: string (url)
* Default: none
* Environment: `CARGO_REGISTRIES_<name>_INDEX`
Specifies the URL of the index for the registry.
-##### `registries.<name>.token`
+#### `registries.<name>.token`
* Type: string
* Default: none
* Environment: `CARGO_REGISTRIES_<name>_TOKEN`
@@ -946,7 +969,23 @@ commands like [`cargo publish`] that require authentication.
Can be overridden with the `--token` command-line option.
-##### `registries.crates-io.protocol`
+#### `registries.<name>.credential-provider`
+* Type: string or array of path and arguments
+* Default: none
+* Environment: `CARGO_REGISTRIES_<name>_CREDENTIAL_PROVIDER`
+
+Specifies the credential provider for the given registry. If not set, the
+providers in [`registry.global-credential-providers`](#registryglobal-credential-providers)
+will be used.
+
+If specified as a string, path and arguments will be split on spaces. For
+paths or arguments that contain spaces, use an array.
+
+If the value exists in the [`[credential-alias]`](#credential-alias) table, the alias will be used.
+
+See [Registry Authentication](registry-authentication.md) for more information.
+
+#### `registries.crates-io.protocol`
* Type: string
* Default: `sparse`
* Environment: `CARGO_REGISTRIES_CRATES_IO_PROTOCOL`
@@ -960,16 +999,16 @@ This can result in a significant performance improvement for resolving new depen
More information about registry protocols may be found in the [Registries chapter](registries.md).
-#### `[registry]`
+### `[registry]`
The `[registry]` table controls the default registry used when one is not
specified.
-##### `registry.index`
+#### `registry.index`
This value is no longer accepted and should not be used.
-##### `registry.default`
+#### `registry.default`
* Type: string
* Default: `"crates-io"`
* Environment: `CARGO_REGISTRY_DEFAULT`
@@ -979,7 +1018,23 @@ by default for registry commands like [`cargo publish`].
Can be overridden with the `--registry` command-line option.
-##### `registry.token`
+#### `registry.credential-provider`
+* Type: string or array of path and arguments
+* Default: none
+* Environment: `CARGO_REGISTRY_CREDENTIAL_PROVIDER`
+
+Specifies the credential provider for [crates.io]. If not set, the
+providers in [`registry.global-credential-providers`](#registryglobal-credential-providers)
+will be used.
+
+If specified as a string, path and arguments will be split on spaces. For
+paths or arguments that contain spaces, use an array.
+
+If the value exists in the `[credential-alias]` table, the alias will be used.
+
+See [Registry Authentication](registry-authentication.md) for more information.
+
+#### `registry.token`
* Type: string
* Default: none
* Environment: `CARGO_REGISTRY_TOKEN`
@@ -990,49 +1045,64 @@ commands like [`cargo publish`] that require authentication.
Can be overridden with the `--token` command-line option.
-#### `[source]`
+#### `registry.global-credential-providers`
+* Type: array
+* Default: `["cargo:token"]`
+* Environment: `CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS`
+
+Specifies the list of global credential providers. If credential provider is not set
+for a specific registry using `registries.<name>.credential-provider`, Cargo will use
+the credential providers in this list. Providers toward the end of the list have precedence.
+
+Path and arguments are split on spaces. If the path or arguments contains spaces, the credential
+provider should be defined in the [`[credential-alias]`](#credential-alias) table and
+referenced here by its alias.
+
+See [Registry Authentication](registry-authentication.md) for more information.
+
+### `[source]`
The `[source]` table defines the registry sources available. See [Source
Replacement] for more information. It consists of a sub-table for each named
source. A source should only define one kind (directory, registry,
local-registry, or git).
-##### `source.<name>.replace-with`
+#### `source.<name>.replace-with`
* Type: string
* Default: none
* Environment: not supported
If set, replace this source with the given named source or named registry.
-##### `source.<name>.directory`
+#### `source.<name>.directory`
* Type: string (path)
* Default: none
* Environment: not supported
Sets the path to a directory to use as a directory source.
-##### `source.<name>.registry`
+#### `source.<name>.registry`
* Type: string (url)
* Default: none
* Environment: not supported
Sets the URL to use for a registry source.
-##### `source.<name>.local-registry`
+#### `source.<name>.local-registry`
* Type: string (path)
* Default: none
* Environment: not supported
Sets the path to a directory to use as a local registry source.
-##### `source.<name>.git`
+#### `source.<name>.git`
* Type: string (url)
* Default: none
* Environment: not supported
Sets the URL to use for a git repository source.
-##### `source.<name>.branch`
+#### `source.<name>.branch`
* Type: string
* Default: none
* Environment: not supported
@@ -1041,7 +1111,7 @@ Sets the branch name to use for a git repository.
If none of `branch`, `tag`, or `rev` is set, defaults to the `master` branch.
-##### `source.<name>.tag`
+#### `source.<name>.tag`
* Type: string
* Default: none
* Environment: not supported
@@ -1050,7 +1120,7 @@ Sets the tag name to use for a git repository.
If none of `branch`, `tag`, or `rev` is set, defaults to the `master` branch.
-##### `source.<name>.rev`
+#### `source.<name>.rev`
* Type: string
* Default: none
* Environment: not supported
@@ -1060,7 +1130,7 @@ Sets the [revision] to use for a git repository.
If none of `branch`, `tag`, or `rev` is set, defaults to the `master` branch.
-#### `[target]`
+### `[target]`
The `[target]` table is used for specifying settings for specific platform
targets. It consists of a sub-table which is either a [platform triple][target triple]
@@ -1086,11 +1156,11 @@ to view), values set by [build scripts], and extra `--cfg` flags passed to
If using a target spec JSON file, the [`<triple>`] value is the filename stem.
For example `--target foo/bar.json` would match `[target.bar]`.
-##### `target.<triple>.ar`
+#### `target.<triple>.ar`
This option is deprecated and unused.
-##### `target.<triple>.linker`
+#### `target.<triple>.linker`
* Type: string (program path)
* Default: none
* Environment: `CARGO_TARGET_<triple>_LINKER`
@@ -1098,7 +1168,13 @@ This option is deprecated and unused.
Specifies the linker which is passed to `rustc` (via [`-C linker`]) when the
[`<triple>`] is being compiled for. By default, the linker is not overridden.
-##### `target.<triple>.runner`
+#### `target.<cfg>.linker`
+This is similar to the [target linker](#targettriplelinker), but using
+a [`cfg()` expression]. If both a [`<triple>`] and `<cfg>` runner match,
+the `<triple>` will take precedence. It is an error if more than one
+`<cfg>` runner matches the current target.
+
+#### `target.<triple>.runner`
* Type: string or array of strings ([program path with args])
* Default: none
* Environment: `CARGO_TARGET_<triple>_RUNNER`
@@ -1108,14 +1184,14 @@ executed by invoking the specified runner with the actual executable passed as
an argument. This applies to [`cargo run`], [`cargo test`] and [`cargo bench`]
commands. By default, compiled executables are executed directly.
-##### `target.<cfg>.runner`
+#### `target.<cfg>.runner`
This is similar to the [target runner](#targettriplerunner), but using
a [`cfg()` expression]. If both a [`<triple>`] and `<cfg>` runner match,
the `<triple>` will take precedence. It is an error if more than one
`<cfg>` runner matches the current target.
-##### `target.<triple>.rustflags`
+#### `target.<triple>.rustflags`
* Type: string or array of strings
* Default: none
* Environment: `CARGO_TARGET_<triple>_RUSTFLAGS`
@@ -1126,13 +1202,13 @@ The value may be an array of strings or a space-separated string.
See [`build.rustflags`](#buildrustflags) for more details on the different
ways to specific extra flags.
-##### `target.<cfg>.rustflags`
+#### `target.<cfg>.rustflags`
This is similar to the [target rustflags](#targettriplerustflags), but
using a [`cfg()` expression]. If several `<cfg>` and [`<triple>`] entries
match the current target, the flags are joined together.
-##### `target.<triple>.<links>`
+#### `target.<triple>.<links>`
The links sub-table provides a way to [override a build script]. When
specified, the build script for the given `links` library will not be
@@ -1150,11 +1226,11 @@ metadata_key1 = "value"
metadata_key2 = "value"
```
-#### `[term]`
+### `[term]`
The `[term]` table controls terminal output and interaction.
-##### `term.quiet`
+#### `term.quiet`
* Type: boolean
* Default: false
* Environment: `CARGO_TERM_QUIET`
@@ -1164,7 +1240,7 @@ Controls whether or not log messages are displayed by Cargo.
Specifying the `--quiet` flag will override and force quiet output.
Specifying the `--verbose` flag will override and disable quiet output.
-##### `term.verbose`
+#### `term.verbose`
* Type: boolean
* Default: false
* Environment: `CARGO_TERM_VERBOSE`
@@ -1174,7 +1250,7 @@ Controls whether or not extra detailed messages are displayed by Cargo.
Specifying the `--quiet` flag will override and disable verbose output.
Specifying the `--verbose` flag will override and force verbose output.
-##### `term.color`
+#### `term.color`
* Type: string
* Default: "auto"
* Environment: `CARGO_TERM_COLOR`
@@ -1188,7 +1264,7 @@ Controls whether or not colored output is used in the terminal. Possible values:
Can be overridden with the `--color` command-line option.
-##### `term.progress.when`
+#### `term.progress.when`
* Type: string
* Default: "auto"
* Environment: `CARGO_TERM_PROGRESS_WHEN`
@@ -1199,7 +1275,7 @@ Controls whether or not progress bar is shown in the terminal. Possible values:
* `always`: Always show progress bar.
* `never`: Never show progress bar.
-##### `term.progress.width`
+#### `term.progress.width`
* Type: integer
* Default: none
* Environment: `CARGO_TERM_PROGRESS_WIDTH`
diff --git a/src/tools/cargo/src/doc/src/reference/credential-provider-protocol.md b/src/tools/cargo/src/doc/src/reference/credential-provider-protocol.md
new file mode 100644
index 000000000..31006abee
--- /dev/null
+++ b/src/tools/cargo/src/doc/src/reference/credential-provider-protocol.md
@@ -0,0 +1,237 @@
+# Credential Provider Protocol
+This document describes information for building a Cargo credential provider. For information on
+setting up or using a credential provider, see [Registry Authentication](registry-authentication.md).
+
+When using an external credential provider, Cargo communicates with the credential
+provider using stdin/stdout messages passed as single lines of JSON.
+
+Cargo will always execute the credential provider with the `--cargo-plugin` argument.
+This enables a credential provider executable to have additional functionality beyond
+what Cargo needs. Additional arguments are included in the JSON via the `args` field.
+
+## JSON messages
+The JSON messages in this document have newlines added for readability.
+Actual messages must not contain newlines.
+
+### Credential hello
+* Sent by: credential provider
+* Purpose: used to identify the supported protocols on process startup
+```javascript
+{
+ "v":[1]
+}
+```
+
+Requests sent by Cargo will include a `v` field set to one of the versions listed here.
+If Cargo does not support any of the versions offered by the credential provider, it will issue an
+error and shut down the credential process.
+
+### Registry information
+* Sent by: Cargo
+Not a message by itself. Included in all messages sent by Cargo as the `registry` field.
+```javascript
+{
+ // Index URL of the registry
+ "index-url":"https://github.com/rust-lang/crates.io-index",
+ // Name of the registry in configuration (optional)
+ "name": "crates-io",
+ // HTTP headers received from attempting to access an authenticated registry (optional)
+ "headers": ["WWW-Authenticate: cargo"]
+}
+```
+
+### Login request
+* Sent by: Cargo
+* Purpose: collect and store credentials
+```javascript
+{
+ // Protocol version
+ "v":1,
+ // Action to perform: login
+ "kind":"login",
+ // Registry information (see Registry information)
+ "registry":{"index-url":"sparse+https://registry-url/index/", "name": "my-registry"},
+ // User-specified token from stdin or command line (optional)
+ "token": "<the token value>",
+ // URL that the user could visit to get a token (optional)
+ "login-url": "http://registry-url/login",
+ // Additional command-line args (optional)
+ "args":[]
+}
+```
+
+If the `token` field is set, then the credential provider should use the token provided. If
+the `token` is not set, then the credential provider should prompt the user for a token.
+
+In addition to the arguments that may be passed to the credential provider in
+configuration, `cargo login` also supports passing additional command line args
+via `cargo login -- <additional args>`. These additional arguments will be included
+in the `args` field after any args from Cargo configuration.
+
+### Read request
+* Sent by: Cargo
+* Purpose: Get the credential for reading crate information
+```javascript
+{
+ // Protocol version
+ "v":1,
+ // Request kind: get credentials
+ "kind":"get",
+ // Action to perform: read crate information
+ "operation":"read",
+ // Registry information (see Registry information)
+ "registry":{"index-url":"sparse+https://registry-url/index/", "name": "my-registry"},
+ // Additional command-line args (optional)
+ "args":[]
+}
+```
+
+### Publish request
+* Sent by: Cargo
+* Purpose: Get the credential for publishing a crate
+```javascript
+{
+ // Protocol version
+ "v":1,
+ // Request kind: get credentials
+ "kind":"get",
+ // Action to perform: publish crate
+ "operation":"publish",
+ // Crate name
+ "name":"sample",
+ // Crate version
+ "vers":"0.1.0",
+ // Crate checksum
+ "cksum":"...",
+ // Registry information (see Registry information)
+ "registry":{"index-url":"sparse+https://registry-url/index/", "name": "my-registry"},
+ // Additional command-line args (optional)
+ "args":[]
+}
+```
+
+### Get success response
+* Sent by: credential provider
+* Purpose: Gives the credential to Cargo
+```javascript
+{"Ok":{
+ // Response kind: this was a get request
+ "kind":"get",
+ // Token to send to the registry
+ "token":"...",
+ // Cache control. Can be one of the following:
+ // * "never": do not cache
+ // * "session": cache for the current cargo session
+ // * "expires": cache for the current cargo session until expiration
+ "cache":"expires",
+ // Unix timestamp (only for "cache": "expires")
+ "expiration":1693942857,
+ // Is the token operation independent?
+ "operation_independent":true
+}}
+```
+
+The `token` will be sent to the registry as the value of the `Authorization` HTTP header.
+
+`operation_independent` indicates whether the token can be cached across different
+operations (such as publishing or fetching). In general, this should be `true` unless
+the provider wants to generate tokens that are scoped to specific operations.
+
+### Login success response
+* Sent by: credential provider
+* Purpose: Indicates the login was successful
+```javascript
+{"Ok":{
+ // Response kind: this was a login request
+ "kind":"login"
+}}
+```
+
+### Logout success response
+* Sent by: credential provider
+* Purpose: Indicates the logout was successful
+```javascript
+{"Ok":{
+ // Response kind: this was a logout request
+ "kind":"logout"
+}}
+```
+
+### Failure response (URL not supported)
+* Sent by: credential provider
+* Purpose: Gives error information to Cargo
+```javascript
+{"Err":{
+ "kind":"url-not-supported"
+}}
+```
+Sent if the credential provider is designed
+to only handle specific registry URLs and the given URL
+is not supported. Cargo will attempt another provider if
+available.
+
+### Failure response (not found)
+* Sent by: credential provider
+* Purpose: Gives error information to Cargo
+```javascript
+{"Err":{
+ // Error: The credential could not be found in the provider.
+ "kind":"not-found"
+}}
+```
+Sent if the credential could not be found. This is expected for
+`get` requests where the credential is not available, or `logout`
+requests where there is nothing found to erase.
+
+### Failure response (operation not supported)
+* Sent by: credential provider
+* Purpose: Gives error information to Cargo
+```javascript
+{"Err":{
+ // Error: The credential could not be found in the provider.
+ "kind":"operation-not-supported"
+}}
+```
+Sent if the credential provider does not support the requested operation.
+If a provider only supports `get` and a `login` is requested, the
+provider should respond with this error.
+
+### Failure response (other)
+* Sent by: credential provider
+* Purpose: Gives error information to Cargo
+```javascript
+{"Err":{
+ // Error: something else has failed
+ "kind":"other",
+ // Error message string to be displayed
+ "message": "free form string error message",
+ // Detailed cause chain for the error (optional)
+ "caused-by": ["cause 1", "cause 2"]
+}}
+```
+
+## Example communication to request a token for reading:
+1. Cargo spawns the credential process, capturing stdin and stdout.
+2. Credential process sends the Hello message to Cargo
+ ```javascript
+ { "v": [1] }
+ ```
+3. Cargo sends the CredentialRequest message to the credential process (newlines added for readability).
+ ```javascript
+ {
+ "v": 1,
+ "kind": "get",
+ "operation": "read",
+ "registry":{"index-url":"sparse+https://registry-url/index/"}
+ }
+ ```
+4. Credential process sends the CredentialResponse to Cargo (newlines added for readability).
+ ```javascript
+ {
+ "token": "...",
+ "cache": "session",
+ "operation_independent": true
+ }
+ ```
+5. Cargo closes the stdin pipe to the credential provider and it exits.
+6. Cargo uses the token for the remainder of the session (until Cargo exits) when interacting with this registry.
diff --git a/src/tools/cargo/src/doc/src/reference/environment-variables.md b/src/tools/cargo/src/doc/src/reference/environment-variables.md
index 25881d138..37c788f8d 100644
--- a/src/tools/cargo/src/doc/src/reference/environment-variables.md
+++ b/src/tools/cargo/src/doc/src/reference/environment-variables.md
@@ -1,10 +1,10 @@
-## Environment Variables
+# Environment Variables
Cargo sets and reads a number of environment variables which your code can detect
or override. Here is a list of the variables Cargo sets, organized by when it interacts
with them:
-### Environment variables Cargo reads
+## Environment variables Cargo reads
You can override these environment variables to change Cargo's behavior on your
system:
@@ -79,7 +79,7 @@ system:
[`cargo fmt`](https://github.com/rust-lang/rustfmt) will execute this specified
`rustfmt` instance instead.
-#### Configuration environment variables
+### Configuration environment variables
Cargo reads environment variables for some configuration values.
See the [configuration chapter][config-env] for more details.
@@ -124,9 +124,12 @@ In summary, the supported environment variables are:
* `CARGO_PROFILE_<name>_RPATH` --- The rpath linking option, see [`profile.<name>.rpath`].
* `CARGO_PROFILE_<name>_SPLIT_DEBUGINFO` --- Controls debug file output behavior, see [`profile.<name>.split-debuginfo`].
* `CARGO_PROFILE_<name>_STRIP` --- Controls stripping of symbols and/or debuginfos, see [`profile.<name>.strip`].
+* `CARGO_REGISTRIES_<name>_CREDENTIAL_PROVIDER` --- Credential provider for a registry, see [`registries.<name>.credential-provider`].
* `CARGO_REGISTRIES_<name>_INDEX` --- URL of a registry index, see [`registries.<name>.index`].
* `CARGO_REGISTRIES_<name>_TOKEN` --- Authentication token of a registry, see [`registries.<name>.token`].
+* `CARGO_REGISTRY_CREDENTIAL_PROVIDER` --- Credential provider for [crates.io], see [`registry.credential-provider`].
* `CARGO_REGISTRY_DEFAULT` --- Default registry for the `--registry` flag, see [`registry.default`].
+* `CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS` --- Credential providers for registries that do not have a specific provider defined. See [`registry.global-credential-providers`].
* `CARGO_REGISTRY_TOKEN` --- Authentication token for [crates.io], see [`registry.token`].
* `CARGO_TARGET_<triple>_LINKER` --- The linker to use, see [`target.<triple>.linker`]. The triple must be [converted to uppercase and underscores](config.md#environment-variables).
* `CARGO_TARGET_<triple>_RUNNER` --- The executable runner, see [`target.<triple>.runner`].
@@ -187,9 +190,12 @@ In summary, the supported environment variables are:
[`profile.<name>.rpath`]: config.md#profilenamerpath
[`profile.<name>.split-debuginfo`]: config.md#profilenamesplit-debuginfo
[`profile.<name>.strip`]: config.md#profilenamestrip
+[`registries.<name>.credential-provider`]: config.md#registriesnamecredential-provider
[`registries.<name>.index`]: config.md#registriesnameindex
[`registries.<name>.token`]: config.md#registriesnametoken
+[`registry.credential-provider`]: config.md#registrycredential-provider
[`registry.default`]: config.md#registrydefault
+[`registry.global-credential-providers`]: config.md#registryglobal-credential-providers
[`registry.token`]: config.md#registrytoken
[`target.<triple>.linker`]: config.md#targettriplelinker
[`target.<triple>.runner`]: config.md#targettriplerunner
@@ -200,7 +206,7 @@ In summary, the supported environment variables are:
[`term.progress.when`]: config.md#termprogresswhen
[`term.progress.width`]: config.md#termprogresswidth
-### Environment variables Cargo sets for crates
+## Environment variables Cargo sets for crates
Cargo exposes these environment variables to your crate when it is compiled.
Note that this applies for running binaries with `cargo run` and `cargo test`
@@ -266,7 +272,7 @@ corresponding environment variable is set to the empty string, `""`.
[integration test]: cargo-targets.md#integration-tests
[`env` macro]: ../../std/macro.env.html
-#### Dynamic library paths
+### Dynamic library paths
Cargo also sets the dynamic library path when compiling and running binaries
with commands like `cargo run` and `cargo test`. This helps with locating
@@ -294,7 +300,7 @@ Cargo includes the following paths:
* The rustc sysroot library path. This generally is not important to most
users.
-### Environment variables Cargo sets for build scripts
+## Environment variables Cargo sets for build scripts
Cargo sets several environment variables when build scripts are run. Because these variables
are not yet set when the build script is compiled, the above example using `env!` won't work
@@ -411,7 +417,7 @@ let out_dir = env::var("OUT_DIR").unwrap();
[`dev`]: profiles.md#dev
[`release`]: profiles.md#release
-### Environment variables Cargo sets for 3rd party subcommands
+## Environment variables Cargo sets for 3rd party subcommands
Cargo exposes this environment variable to 3rd party subcommands
(ie. programs named `cargo-foobar` placed in `$PATH`):
diff --git a/src/tools/cargo/src/doc/src/reference/external-tools.md b/src/tools/cargo/src/doc/src/reference/external-tools.md
index b2f37ca0b..e835ea3ee 100644
--- a/src/tools/cargo/src/doc/src/reference/external-tools.md
+++ b/src/tools/cargo/src/doc/src/reference/external-tools.md
@@ -1,4 +1,4 @@
-## External tools
+# External tools
One of the goals of Cargo is simple integration with third-party tools, like
IDEs and other build systems. To make integration easier, Cargo has several
@@ -13,7 +13,7 @@ facilities:
* support for custom subcommands.
-### Information about package structure
+## Information about package structure
You can use [`cargo metadata`] command to get information about package
structure and dependencies. See the [`cargo metadata`] documentation
@@ -29,7 +29,7 @@ output.
[cargo_metadata]: https://crates.io/crates/cargo_metadata
[`cargo metadata`]: ../commands/cargo-metadata.md
-### JSON messages
+## JSON messages
When passing `--message-format=json`, Cargo will output the following
information during the build:
@@ -54,7 +54,7 @@ messages.
[build command documentation]: ../commands/cargo-build.md
[cargo_metadata]: https://crates.io/crates/cargo_metadata
-#### Compiler messages
+### Compiler messages
The "compiler-message" message includes output from the compiler, such as
warnings and errors. See the [rustc JSON chapter](../../rustc/json.md) for
@@ -125,7 +125,7 @@ structure:
}
```
-#### Artifact messages
+### Artifact messages
For every compilation step, a "compiler-artifact" message is emitted with the
following structure:
@@ -192,7 +192,7 @@ following structure:
```
-#### Build script output
+### Build script output
The "build-script-executed" message includes the parsed output of a build
script. Note that this is emitted even if the build script is not run; it will
@@ -233,7 +233,7 @@ may be found in [the chapter on build scripts](build-scripts.md).
}
```
-#### Build finished
+### Build finished
The "build-finished" message is emitted at the end of the build.
@@ -257,7 +257,7 @@ executed by `cargo run`).
> so additional test-specific JSON messages may begin arriving after the
> "build-finished" message if that is enabled.
-### Custom subcommands
+## Custom subcommands
Cargo is designed to be extensible with new subcommands without having to modify
Cargo itself. This is achieved by translating a cargo invocation of the form
diff --git a/src/tools/cargo/src/doc/src/reference/features-examples.md b/src/tools/cargo/src/doc/src/reference/features-examples.md
index ac9636fcb..810288dda 100644
--- a/src/tools/cargo/src/doc/src/reference/features-examples.md
+++ b/src/tools/cargo/src/doc/src/reference/features-examples.md
@@ -1,8 +1,8 @@
-## Features Examples
+# Features Examples
The following illustrates some real-world examples of features in action.
-### Minimizing build times and file sizes
+## Minimizing build times and file sizes
Some packages use features so that if the features are not enabled, it reduces
the size of the crate and reduces compile time. Some examples are:
@@ -30,7 +30,7 @@ the size of the crate and reduces compile time. Some examples are:
[`web-sys`]: https://crates.io/crates/web-sys
[web-sys-features]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/crates/web-sys/Cargo.toml#L32-L1395
-### Extending behavior
+## Extending behavior
The [`serde_json`] package has a [`preserve_order` feature][serde_json-preserve_order]
which [changes the behavior][serde_json-code] of JSON maps to preserve the
@@ -47,7 +47,7 @@ usually builds with the feature off.
[serde_json-code]: https://github.com/serde-rs/json/blob/v1.0.60/src/map.rs#L23-L26
[`indexmap`]: https://crates.io/crates/indexmap
-### `no_std` support
+## `no_std` support
Some packages want to support both [`no_std`] and `std` environments. This is
useful for supporting embedded and resource-constrained platforms, but still
@@ -71,7 +71,7 @@ to conditionally enable extra functionality that requires `std`.
[wasm-bindgen-cfg1]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/src/lib.rs#L270-L273
[wasm-bindgen-cfg2]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/src/lib.rs#L67-L75
-### Re-exporting dependency features
+## Re-exporting dependency features
It can be convenient to re-export the features from a dependency. This allows
the user depending on the crate to control those features without needing to
@@ -83,7 +83,7 @@ but they can still access the features it contains.
[regex-re-export]: https://github.com/rust-lang/regex/blob/1.4.2/Cargo.toml#L65-L89
[regex_syntax-features]: https://github.com/rust-lang/regex/blob/1.4.2/regex-syntax/Cargo.toml#L17-L32
-### Vendoring of C libraries
+## Vendoring of C libraries
Some packages provide bindings to common C libraries (sometimes referred to as
["sys" crates][sys]). Sometimes these packages give you the choice to use the
@@ -111,7 +111,7 @@ static-curl setting.
[curl-sys-macos]: https://github.com/alexcrichton/curl-rust/blob/0.4.34/curl-sys/Cargo.toml#L52
[curl-sys-macos-code]: https://github.com/alexcrichton/curl-rust/blob/0.4.34/curl-sys/build.rs#L15-L20
-### Feature precedence
+## Feature precedence
Some packages may have mutually-exclusive features. One option to handle this
is to prefer one feature over another. The [`log`] package is an example. It
@@ -126,7 +126,7 @@ levels will be preferred over the lower levels.
[log-cfg-if]: https://github.com/rust-lang/log/blob/0.4.11/src/lib.rs#L1422-L1448
[`cfg-if`]: https://crates.io/crates/cfg-if
-### Proc-macro companion package
+## Proc-macro companion package
Some packages have a proc-macro that is intimately tied with it. However, not
all users will need to use the proc-macro. By making the proc-macro an
@@ -145,7 +145,7 @@ requirement][serde-equals] to ensure they stay in sync.
[serde-derive]: https://github.com/serde-rs/serde/blob/v1.0.118/serde/Cargo.toml#L34-L35
[serde-equals]: https://github.com/serde-rs/serde/blob/v1.0.118/serde/Cargo.toml#L17
-### Nightly-only features
+## Nightly-only features
Some packages want to experiment with APIs or language features that are only
available on the Rust [nightly channel]. However, they may not want to require
@@ -172,7 +172,7 @@ which relies on a dependency that only builds on the nightly channel.
[`rand`]: https://crates.io/crates/rand
[rand-simd_support]: https://github.com/rust-random/rand/blob/0.7.3/Cargo.toml#L40
-### Experimental features
+## Experimental features
Some packages have new functionality that they may want to experiment with,
without having to commit to the stability of those APIs. The features are
diff --git a/src/tools/cargo/src/doc/src/reference/features.md b/src/tools/cargo/src/doc/src/reference/features.md
index 40eb32c41..9e521049c 100644
--- a/src/tools/cargo/src/doc/src/reference/features.md
+++ b/src/tools/cargo/src/doc/src/reference/features.md
@@ -1,4 +1,4 @@
-## Features
+# Features
Cargo "features" provide a mechanism to express [conditional compilation] and
[optional dependencies](#optional-dependencies). A package defines a set of
@@ -13,7 +13,7 @@ be used.
[conditional compilation]: ../../reference/conditional-compilation.md
[Features Examples]: features-examples.md
-### The `[features]` section
+## The `[features]` section
Features are defined in the `[features]` table in `Cargo.toml`. Each feature
specifies an array of other features or optional dependencies that it enables.
@@ -68,7 +68,7 @@ includes most letters), and additionally allows starting with `_` or digits
[`cfg` attribute]: ../../reference/conditional-compilation.md#the-cfg-attribute
[`cfg` macro]: ../../std/macro.cfg.html
-### The `default` feature
+## The `default` feature
By default, all features are disabled unless explicitly enabled. This can be
changed by specifying the `default` feature:
@@ -105,7 +105,7 @@ enables the listed features. This behavior can be changed by:
> change](#semver-compatibility) to remove a feature from the default set, so
> you should be confident that you will keep those features.
-### Optional dependencies
+## Optional dependencies
Dependencies can be marked "optional", which means they will not be compiled
by default. For example, let's say that our 2D image processing library uses
@@ -164,7 +164,7 @@ our crate.
[platform-specific dependencies]: specifying-dependencies.md#platform-specific-dependencies
-### Dependency features
+## Dependency features
Features of dependencies can be enabled within the dependency declaration. The
`features` key indicates which features to enable:
@@ -226,7 +226,7 @@ dependency.
It will also enable the `serde` feature for the `rgb` dependency, but only if
something else has enabled the `rgb` dependency.
-### Command-line feature options
+## Command-line feature options
The following command-line flags can be used to control which features are
enabled:
@@ -246,7 +246,7 @@ enabled:
[workspace]: workspaces.md
-### Feature unification
+## Feature unification
Features are unique to the package that defines them. Enabling a feature on a
package does not enable a feature of the same name on other packages.
@@ -291,7 +291,7 @@ pub fn function_that_requires_std() {
[`no_std`]: ../../reference/names/preludes.html#the-no_std-attribute
[features section]: resolver.md#features
-#### Mutually exclusive features
+### Mutually exclusive features
There are rare cases where features may be mutually incompatible with one
another. This should be avoided if at all possible, because it requires
@@ -318,7 +318,7 @@ Instead of using mutually exclusive features, consider some other options:
[`cfg-if`]: https://crates.io/crates/cfg-if
[feature-precedence]: features-examples.md#feature-precedence
-#### Inspecting resolved features
+### Inspecting resolved features
In complex dependency graphs, it can sometimes be difficult to understand how
different features get enabled on various packages. The [`cargo tree`] command
@@ -338,7 +338,7 @@ enabled. Some options to try:
[`cargo tree`]: ../commands/cargo-tree.md
-### Feature resolver version 2
+## Feature resolver version 2
A different feature resolver can be specified with the `resolver` field in
`Cargo.toml`, like this:
@@ -386,7 +386,7 @@ the resolved features. For build dependencies, this is not necessary if you
are cross-compiling with the `--target` flag because build dependencies are
always built separately from normal dependencies in that scenario.
-#### Resolver version 2 command-line flags
+### Resolver version 2 command-line flags
The `resolver = "2"` setting also changes the behavior of the `--features` and
`--no-default-features` [command-line options](#command-line-feature-options).
@@ -419,7 +419,7 @@ version "2", it will disable the default features for all workspace members.
[dev-dependencies]: specifying-dependencies.md#development-dependencies
[resolver-v2]: resolver.md#feature-resolver-version-2
-### Build scripts
+## Build scripts
[Build scripts] can detect which features are enabled on the package by
inspecting the `CARGO_FEATURE_<name>` environment variable, where `<name>` is
@@ -427,7 +427,7 @@ the feature name converted to uppercase and `-` converted to `_`.
[build scripts]: build-scripts.md
-### Required features
+## Required features
The [`required-features` field] can be used to disable specific [Cargo
targets] if a feature is not enabled. See the linked documentation for more
@@ -436,7 +436,7 @@ details.
[`required-features` field]: cargo-targets.md#the-required-features-field
[Cargo targets]: cargo-targets.md
-### SemVer compatibility
+## SemVer compatibility
Enabling a feature should not introduce a SemVer-incompatible change. For
example, the feature shouldn't change an existing API in a way that could
@@ -466,7 +466,7 @@ See the links for caveats and examples.
[cargo-remove-opt-dep]: semver.md#cargo-remove-opt-dep
[cargo-feature-remove-another]: semver.md#cargo-feature-remove-another
-### Feature documentation and discovery
+## Feature documentation and discovery
You are encouraged to document which features are available in your package.
This can be done by adding [doc comments] at the top of `lib.rs`. As an
@@ -501,7 +501,7 @@ control which features are enabled when the documentation is built. See
[`doc_cfg`]: ../../unstable-book/language-features/doc-cfg.html
[`syn` documentation]: https://docs.rs/syn/1.0.54/syn/#modules
-#### Discovering features
+### Discovering features
When features are documented in the library API, this can make it easier for
your users to discover which features are available and what they do. If the
@@ -514,7 +514,7 @@ source and inspect it.
[`cargo vendor`]: ../commands/cargo-vendor.md
[cargo-clone-crate]: https://crates.io/crates/cargo-clone-crate
-### Feature combinations
+## Feature combinations
Because features are a form of conditional compilation, they require an exponential number of configurations and test cases to be 100% covered. By default, tests, docs, and other tooling such as [Clippy](https://github.com/rust-lang/rust-clippy) will only run with the default set of features.
diff --git a/src/tools/cargo/src/doc/src/reference/future-incompat-report.md b/src/tools/cargo/src/doc/src/reference/future-incompat-report.md
index b72f11757..ab394572f 100644
--- a/src/tools/cargo/src/doc/src/reference/future-incompat-report.md
+++ b/src/tools/cargo/src/doc/src/reference/future-incompat-report.md
@@ -1,4 +1,4 @@
-### Future incompat report
+# Future incompat report
Cargo checks for future-incompatible warnings in all dependencies. These are warnings for
changes that may become hard errors in the future, causing the dependency to
diff --git a/src/tools/cargo/src/doc/src/reference/index.md b/src/tools/cargo/src/doc/src/reference/index.md
index b931306c2..afff4fa89 100644
--- a/src/tools/cargo/src/doc/src/reference/index.md
+++ b/src/tools/cargo/src/doc/src/reference/index.md
@@ -1,4 +1,4 @@
-## Cargo Reference
+# Cargo Reference
The reference covers the details of various areas of Cargo.
diff --git a/src/tools/cargo/src/doc/src/reference/manifest.md b/src/tools/cargo/src/doc/src/reference/manifest.md
index 5f9d29ff6..5ecbe5117 100644
--- a/src/tools/cargo/src/doc/src/reference/manifest.md
+++ b/src/tools/cargo/src/doc/src/reference/manifest.md
@@ -1,4 +1,4 @@
-## The Manifest Format
+# The Manifest Format
The `Cargo.toml` file for each package is called its *manifest*. It is written
in the [TOML] format. It contains metadata that is needed to compile the package. Checkout
@@ -48,12 +48,13 @@ Every manifest file consists of the following sections:
* [`[target]`](specifying-dependencies.md#platform-specific-dependencies) --- Platform-specific dependencies.
* [`[badges]`](#the-badges-section) --- Badges to display on a registry.
* [`[features]`](features.md) --- Conditional compilation features.
+* [`[lints]`](#the-lints-section) --- Configure linters for this package.
* [`[patch]`](overriding-dependencies.md#the-patch-section) --- Override dependencies.
* [`[replace]`](overriding-dependencies.md#the-replace-section) --- Override dependencies (deprecated).
* [`[profile]`](profiles.md) --- Compiler settings and optimizations.
* [`[workspace]`](workspaces.md) --- The workspace definition.
-### The `[package]` section
+## The `[package]` section
The first section in a `Cargo.toml` is `[package]`.
@@ -69,7 +70,7 @@ The only fields required by Cargo are [`name`](#the-name-field) and
require additional fields. See the notes below and [the publishing
chapter][publishing] for requirements for publishing to [crates.io].
-#### The `name` field
+### The `name` field
The package name is an identifier used to refer to the package. It is used
when listed as a dependency in another package, and as the default name of
@@ -88,7 +89,7 @@ a keyword. [crates.io] imposes even more restrictions, such as:
[alphanumeric]: ../../std/primitive.char.html#method.is_alphanumeric
-#### The `version` field
+### The `version` field
Cargo bakes in the concept of [Semantic
Versioning](https://semver.org/), so make sure you follow some basic rules:
@@ -111,7 +112,7 @@ breaking change.
[Resolver]: resolver.md
[SemVer compatibility]: semver.md
-#### The `authors` field
+### The `authors` field
The optional `authors` field lists in an array the people or organizations that are considered
the "authors" of the package. The exact meaning is open to interpretation --- it
@@ -133,7 +134,7 @@ user interface.
> field cannot be changed or removed in already-published versions of a
> package.
-#### The `edition` field
+### The `edition` field
The `edition` key is an optional key that affects which [Rust Edition] your package
is compiled with. Setting the `edition` key in `[package]` will affect all
@@ -155,7 +156,7 @@ assumed for backwards compatibility. Note that all manifests
created with [`cargo new`] will not use this historical fallback because they
will have `edition` explicitly specified to a newer value.
-#### The `rust-version` field
+### The `rust-version` field
The `rust-version` field is an optional key that tells cargo what version of the
Rust language and compiler your package can be compiled with. If the currently
@@ -182,7 +183,7 @@ The `rust-version` may be ignored using the `--ignore-rust-version` option.
Setting the `rust-version` key in `[package]` will affect all targets/crates in
the package, including test suites, benchmarks, binaries, examples, etc.
-#### The `description` field
+### The `description` field
The description is a short blurb about the package. [crates.io] will display
this with your package. This should be plain text (not Markdown).
@@ -195,7 +196,7 @@ description = "A short description of my package"
> **Note**: [crates.io] requires the `description` to be set.
-#### The `documentation` field
+### The `documentation` field
The `documentation` field specifies a URL to a website hosting the crate's
documentation. If no URL is specified in the manifest file, [crates.io] will
@@ -210,7 +211,7 @@ documentation = "https://docs.rs/bitflags"
[docs.rs queue]: https://docs.rs/releases/queue
-#### The `readme` field
+### The `readme` field
The `readme` field should be the path to a file in the package root (relative
to this `Cargo.toml`) that contains general information about the package.
@@ -229,7 +230,7 @@ file will be used. You can suppress this behavior by setting this field to
`false`. If the field is set to `true`, a default value of `README.md` will
be assumed.
-#### The `homepage` field
+### The `homepage` field
The `homepage` field should be a URL to a site that is the home page for your
package.
@@ -240,7 +241,7 @@ package.
homepage = "https://serde.rs/"
```
-#### The `repository` field
+### The `repository` field
The `repository` field should be a URL to the source repository for your
package.
@@ -251,7 +252,7 @@ package.
repository = "https://github.com/rust-lang/cargo/"
```
-#### The `license` and `license-file` fields
+### The `license` and `license-file` fields
The `license` field contains the name of the software license that the package
is released under. The `license-file` field contains the path to a file
@@ -293,7 +294,7 @@ license-file = "LICENSE.txt"
[^slash]: Previously multiple licenses could be separated with a `/`, but that
usage is deprecated.
-#### The `keywords` field
+### The `keywords` field
The `keywords` field is an array of strings that describe this package. This
can help when searching for the package on a registry, and you may choose any
@@ -305,11 +306,11 @@ words that would help someone find this crate.
keywords = ["gamedev", "graphics"]
```
-> **Note**: [crates.io] has a maximum of 5 keywords. Each keyword must be
-> ASCII text, start with a letter, and only contain letters, numbers, `_` or
-> `-`, and have at most 20 characters.
+> **Note**: [crates.io] allows a maximum of 5 keywords. Each keyword must be
+> ASCII text, have at most 20 characters, start with an alphanumeric character,
+> and only contain letters, numbers, `_`, `-` or `+`.
-#### The `categories` field
+### The `categories` field
The `categories` field is an array of strings of the categories this package
belongs to.
@@ -322,7 +323,7 @@ categories = ["command-line-utilities", "development-tools::cargo-plugins"]
> match one of the strings available at <https://crates.io/category_slugs>, and
> must match exactly.
-#### The `workspace` field
+### The `workspace` field
The `workspace` field can be used to configure the workspace that this package
will be a member of. If not specified this will be inferred as the first
@@ -342,7 +343,7 @@ table defined. That is, a crate cannot both be a root crate in a workspace
For more information, see the [workspaces chapter](workspaces.md).
-#### The `build` field
+### The `build` field
The `build` field specifies a file in the package root which is a [build
script] for building native code. More information can be found in the [build
@@ -361,7 +362,7 @@ The default is `"build.rs"`, which loads the script from a file named
specify a path to a different file or `build = false` to disable automatic
detection of the build script.
-#### The `links` field
+### The `links` field
The `links` field specifies the name of a native library that is being linked
to. More information can be found in the [`links`][links] section of the build
@@ -378,7 +379,7 @@ on Linux) may specify:
links = "git2"
```
-#### The `exclude` and `include` fields
+### The `exclude` and `include` fields
The `exclude` and `include` fields can be used to explicitly specify which
files are included when packaging a project to be [published][publishing],
@@ -467,7 +468,7 @@ if any of those files change.
[gitignore]: https://git-scm.com/docs/gitignore
-#### The `publish` field
+### The `publish` field
The `publish` field can be used to prevent a package from being published to a
package registry (like *crates.io*) by mistake, for instance to keep a package
@@ -491,7 +492,7 @@ publish = ["some-registry-name"]
If publish array contains a single registry, `cargo publish` command will use
it when `--registry` flag is not specified.
-#### The `metadata` table
+### The `metadata` table
Cargo by default will warn about unused keys in `Cargo.toml` to assist in
detecting typos and such. The `package.metadata` table, however, is completely
@@ -519,7 +520,7 @@ if that makes sense for the tool in question.
[workspace-metadata]: workspaces.md#the-metadata-table
-#### The `default-run` field
+### The `default-run` field
The `default-run` field in the `[package]` section of the manifest can be used
to specify a default binary picked by [`cargo run`]. For example, when there is
@@ -530,7 +531,47 @@ both `src/bin/a.rs` and `src/bin/b.rs`:
default-run = "a"
```
-### The `[badges]` section
+#### The `lints` section
+
+Override the default level of lints from different tools by assigning them to a new level in a
+table, for example:
+```toml
+[lints.rust]
+unsafe_code = "forbid"
+```
+
+This is short-hand for:
+```toml
+[lints.rust]
+unsafe_code = { level = "forbid", priority = 0 }
+```
+
+`level` corresponds to the lint levels in `rustc`:
+- `forbid`
+- `deny`
+- `warn`
+- `allow`
+
+`priority` is a signed integer that controls which lints or lint groups override other lint groups:
+- lower (particularly negative) numbers have lower priority, being overridden
+ by higher numbers, and show up first on the command-line to tools like
+ `rustc`
+
+To know which table under `[lints]` a particular lint belongs under, it is the part before `::` in the lint
+name. If there isn't a `::`, then the tool is `rust`. For example a warning
+about `unsafe_code` would be `lints.rust.unsafe_code` but a lint about
+`clippy::enum_glob_use` would be `lints.clippy.enum_glob_use`.
+
+For example:
+```toml
+[lints.rust]
+unsafe_code = "forbid"
+
+[lints.clippy]
+enum_glob_use = "deny"
+```
+
+## The `[badges]` section
The `[badges]` section is for specifying status badges that can be displayed
on a registry website when the package is published.
@@ -565,13 +606,13 @@ on a registry website when the package is published.
maintenance = { status = "..." }
```
-### Dependency sections
+## Dependency sections
See the [specifying dependencies page](specifying-dependencies.md) for
information on the `[dependencies]`, `[dev-dependencies]`,
`[build-dependencies]`, and target-specific `[target.*.dependencies]` sections.
-### The `[profile.*]` sections
+## The `[profile.*]` sections
The `[profile]` tables provide a way to customize compiler settings such as
optimizations and debug settings. See [the Profiles chapter](profiles.md) for
diff --git a/src/tools/cargo/src/doc/src/reference/overriding-dependencies.md b/src/tools/cargo/src/doc/src/reference/overriding-dependencies.md
index c04a7929d..6d80df198 100644
--- a/src/tools/cargo/src/doc/src/reference/overriding-dependencies.md
+++ b/src/tools/cargo/src/doc/src/reference/overriding-dependencies.md
@@ -1,4 +1,4 @@
-## Overriding Dependencies
+# Overriding Dependencies
The desire to override a dependency can arise through a number of scenarios.
Most of them, however, boil down to the ability to work with a crate before
@@ -37,7 +37,7 @@ on the different ways to override a dependency.
> can be used to override the source for a single dependency declaration in a
> local package.
-### Testing a bugfix
+## Testing a bugfix
Let's say you're working with the [`uuid` crate] but while you're working on it
you discover a bug. You are, however, quite enterprising so you decide to also
@@ -97,7 +97,7 @@ $ cargo build
And that's it! You're now building with the local version of `uuid` (note the
path in parentheses in the build output). If you don't see the local path version getting
-built then you may need to run `cargo update -p uuid --precise $version` where
+built then you may need to run `cargo update uuid --precise $version` where
`$version` is the version of the locally checked out copy of `uuid`.
Once you've fixed the bug you originally found the next thing you'll want to do
@@ -113,7 +113,7 @@ uuid = { git = 'https://github.com/uuid-rs/uuid.git' }
[uuid-repository]: https://github.com/uuid-rs/uuid
-### Working with an unpublished minor version
+## Working with an unpublished minor version
Let's now shift gears a bit from bug fixes to adding features. While working on
`my-library` you discover that a whole new feature is needed in the `uuid`
@@ -171,7 +171,7 @@ if necessary. Here, though, the new `uuid` crate applies to *both* our dependenc
one version for this entire crate graph, 1.0.1, and it'll be pulled from the git
repository.
-#### Overriding repository URL
+### Overriding repository URL
In case the dependency you want to override isn't loaded from `crates.io`,
you'll have to change a bit how you use `[patch]`. For example, if the
@@ -184,7 +184,7 @@ my-library = { path = "../my-library/path" }
And that's it!
-### Prepublishing a breaking change
+## Prepublishing a breaking change
Let's take a look at working with a new major version of a crate, typically
accompanied with breaking changes. Sticking with our previous crates, this
@@ -224,7 +224,7 @@ the `my-library` crate will use the `2.0.0` version of `uuid`. This will allow y
to gradually roll out breaking changes to a crate through a dependency graph
without being forced to update everything all at once.
-### Using `[patch]` with multiple versions
+## Using `[patch]` with multiple versions
You can patch in multiple versions of the same crate with the `package` key
used to rename dependencies. For example let's say that the `serde` crate has
@@ -248,7 +248,7 @@ Note that when using the `package` key the `serde2` identifier here is actually
ignored. We simply need a unique name which doesn't conflict with other patched
crates.
-### The `[patch]` section
+## The `[patch]` section
The `[patch]` section of `Cargo.toml` can be used to override dependencies
with other copies. The syntax is similar to the
@@ -295,7 +295,7 @@ Cargo only looks at the patch settings in the `Cargo.toml` manifest at the
root of the workspace. Patch settings defined in dependencies will be
ignored.
-### The `[replace]` section
+## The `[replace]` section
> **Note**: `[replace]` is deprecated. You should use the
> [`[patch]`](#the-patch-section) table instead.
@@ -321,7 +321,7 @@ Cargo only looks at the replace settings in the `Cargo.toml` manifest at the
root of the workspace. Replace settings defined in dependencies will be
ignored.
-### `paths` overrides
+## `paths` overrides
Sometimes you're only temporarily working on a crate and you don't want to have
to modify `Cargo.toml` like with the `[patch]` section above. For this use
diff --git a/src/tools/cargo/src/doc/src/reference/pkgid-spec.md b/src/tools/cargo/src/doc/src/reference/pkgid-spec.md
index 6c11b4b3d..7f20973b5 100644
--- a/src/tools/cargo/src/doc/src/reference/pkgid-spec.md
+++ b/src/tools/cargo/src/doc/src/reference/pkgid-spec.md
@@ -1,6 +1,6 @@
-## Package ID Specifications
+# Package ID Specifications
-### Package ID specifications
+## Package ID specifications
Subcommands of Cargo frequently need to refer to a particular package within a
dependency graph for various operations like updating, cleaning, building, etc.
@@ -16,7 +16,7 @@ ambiguity, additional qualifiers can be added to make it unique. For example,
if there are two versions of the `regex` package in the graph, then it can be
qualified with a version to make it unique, such as `regex@1.4.3`.
-#### Specification grammar
+### Specification grammar
The formal grammar for a Package Id Specification is:
@@ -24,6 +24,7 @@ The formal grammar for a Package Id Specification is:
spec := pkgname
| proto "://" hostname-and-path [ "#" ( pkgname | semver ) ]
pkgname := name [ ("@" | ":" ) semver ]
+semver := digits [ "." digits [ "." digits [ "-" prerelease ] [ "+" build ]]]
proto := "http" | "git" | ...
```
@@ -33,13 +34,14 @@ Here, brackets indicate that the contents are optional.
The URL form can be used for git dependencies, or to differentiate packages
that come from different sources such as different registries.
-#### Example specifications
+### Example specifications
The following are references to the `regex` package on `crates.io`:
| Spec | Name | Version |
|:------------------------------------------------------------|:-------:|:-------:|
| `regex` | `regex` | `*` |
+| `regex@1.4` | `regex` | `1.4.*` |
| `regex@1.4.3` | `regex` | `1.4.3` |
| `https://github.com/rust-lang/crates.io-index#regex` | `regex` | `*` |
| `https://github.com/rust-lang/crates.io-index#regex@1.4.3` | `regex` | `1.4.3` |
@@ -59,7 +61,7 @@ Local packages on the filesystem can use `file://` URLs to reference them:
| `file:///path/to/my/project/foo` | `foo` | `*` |
| `file:///path/to/my/project/foo#1.1.8` | `foo` | `1.1.8` |
-#### Brevity of specifications
+### Brevity of specifications
The goal of this is to enable both succinct and exhaustive syntaxes for
referring to packages in a dependency graph. Ambiguous references may refer to
diff --git a/src/tools/cargo/src/doc/src/reference/profiles.md b/src/tools/cargo/src/doc/src/reference/profiles.md
index c094aa815..15ca8953c 100644
--- a/src/tools/cargo/src/doc/src/reference/profiles.md
+++ b/src/tools/cargo/src/doc/src/reference/profiles.md
@@ -1,4 +1,4 @@
-## Profiles
+# Profiles
Profiles provide a way to alter the compiler settings, influencing things like
optimizations and debugging symbols.
@@ -28,11 +28,11 @@ the settings from `Cargo.toml`.
[config]: config.md
-### Profile settings
+## Profile settings
The following is a list of settings that can be controlled in a profile.
-#### opt-level
+### opt-level
The `opt-level` setting controls the [`-C opt-level` flag] which controls the level
of optimization. Higher optimization levels may produce faster runtime code at
@@ -60,7 +60,7 @@ techniques.
[`-C opt-level` flag]: ../../rustc/codegen-options/index.html#opt-level
[Profile Guided Optimization]: ../../rustc/profile-guided-optimization.html
-#### debug
+### debug
The `debug` setting controls the [`-C debuginfo` flag] which controls the
amount of debug information included in the compiled binary.
@@ -82,7 +82,7 @@ depending on your needs as well.
[debuginfo]: ../../rustc/codegen-options/index.html#debuginfo
[profiling]: https://reviews.llvm.org/D46061
-#### split-debuginfo
+### split-debuginfo
The `split-debuginfo` setting controls the [`-C split-debuginfo` flag] which
controls whether debug information, if generated, is either placed in the
@@ -96,10 +96,14 @@ split-debuginfo` flag] and is platform-specific. Some options are only
available on the [nightly channel]. The Cargo default may change in the future
once more testing has been performed, and support for DWARF is stabilized.
+Be aware that Cargo and rustc have different defaults for this option. This
+option exists to allow Cargo to experiment on different combinations of flags
+thus providing better debugging and developer experience.
+
[nightly channel]: ../../book/appendix-07-nightly-rust.html
[`-C split-debuginfo` flag]: ../../rustc/codegen-options/index.html#split-debuginfo
-#### strip
+### strip
The `strip` option controls the [`-C strip` flag], which directs rustc to
strip either symbols or debuginfo from a binary. This can be enabled like so:
@@ -121,7 +125,7 @@ equivalent to `strip = "none"` and disables `strip` completely.
[`-C strip` flag]: ../../rustc/codegen-options/index.html#strip
-#### debug-assertions
+### debug-assertions
The `debug-assertions` setting controls the [`-C debug-assertions` flag] which
turns `cfg(debug_assertions)` [conditional compilation] on or off. Debug
@@ -139,7 +143,7 @@ The valid options are:
[conditional compilation]: ../../reference/conditional-compilation.md#debug_assertions
[`debug_assert!` macro]: ../../std/macro.debug_assert.html
-#### overflow-checks
+### overflow-checks
The `overflow-checks` setting controls the [`-C overflow-checks` flag] which
controls the behavior of [runtime integer overflow]. When overflow-checks are
@@ -153,7 +157,7 @@ The valid options are:
[`-C overflow-checks` flag]: ../../rustc/codegen-options/index.html#overflow-checks
[runtime integer overflow]: ../../reference/expressions/operator-expr.md#overflow
-#### lto
+### lto
The `lto` setting controls `rustc`'s [`-C lto`], [`-C linker-plugin-lto`], and
[`-C embed-bitcode`] options, which control LLVM's [link time optimizations].
@@ -183,7 +187,7 @@ This is not yet supported natively in Cargo, but can be performed via
[linker-plugin-lto chapter]: ../../rustc/linker-plugin-lto.html
["thin" LTO]: http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html
-#### panic
+### panic
The `panic` setting controls the [`-C panic` flag] which controls which panic
strategy to use.
@@ -207,7 +211,7 @@ dependencies will also be forced to build with the `unwind` strategy.
[`-C panic` flag]: ../../rustc/codegen-options/index.html#panic
[`panic-abort-tests`]: unstable.md#panic-abort-tests
-#### incremental
+### incremental
The `incremental` setting controls the [`-C incremental` flag] which controls
whether or not incremental compilation is enabled. Incremental compilation
@@ -230,7 +234,7 @@ The incremental value can be overridden globally with the `CARGO_INCREMENTAL`
[environment variable]: environment-variables.md
[`build.incremental`]: config.md#buildincremental
-#### codegen-units
+### codegen-units
The `codegen-units` setting controls the [`-C codegen-units` flag] which
controls how many "code generation units" a crate will be split into. More
@@ -244,7 +248,7 @@ non-incremental builds.
[`-C codegen-units` flag]: ../../rustc/codegen-options/index.html#codegen-units
-#### rpath
+### rpath
The `rpath` setting controls the [`-C rpath` flag] which controls
whether or not [`rpath`] is enabled.
@@ -252,9 +256,9 @@ whether or not [`rpath`] is enabled.
[`-C rpath` flag]: ../../rustc/codegen-options/index.html#rpath
[`rpath`]: https://en.wikipedia.org/wiki/Rpath
-### Default profiles
+## Default profiles
-#### dev
+### dev
The `dev` profile is used for normal development and debugging. It is the
default for build commands like [`cargo build`], and is used for `cargo install --debug`.
@@ -266,6 +270,7 @@ The default settings for the `dev` profile are:
opt-level = 0
debug = true
split-debuginfo = '...' # Platform-specific.
+strip = false
debug-assertions = true
overflow-checks = true
lto = false
@@ -275,7 +280,7 @@ codegen-units = 256
rpath = false
```
-#### release
+### release
The `release` profile is intended for optimized artifacts used for releases
and in production. This profile is used when the `--release` flag is used, and
@@ -288,6 +293,7 @@ The default settings for the `release` profile are:
opt-level = 3
debug = false
split-debuginfo = '...' # Platform-specific.
+strip = false
debug-assertions = false
overflow-checks = false
lto = false
@@ -297,17 +303,17 @@ codegen-units = 16
rpath = false
```
-#### test
+### test
The `test` profile is the default profile used by [`cargo test`].
The `test` profile inherits the settings from the [`dev`](#dev) profile.
-#### bench
+### bench
The `bench` profile is the default profile used by [`cargo bench`].
The `bench` profile inherits the settings from the [`release`](#release) profile.
-#### Build Dependencies
+### Build Dependencies
To compile quickly, all profiles, by default, do not optimize build
dependencies (build scripts, proc macros, and their dependencies), and avoid
@@ -335,7 +341,7 @@ debug = true
Build dependencies otherwise inherit settings from the active profile in use, as
described in [Profile selection](#profile-selection).
-### Custom profiles
+## Custom profiles
In addition to the built-in profiles, additional custom profiles can be
defined. These may be useful for setting up multiple workflows and build
@@ -365,7 +371,7 @@ output would go into the `target/release-lto` directory.
[`target` directory]: ../guide/build-cache.md
-### Profile selection
+## Profile selection
The profile used depends on the command, the command-line flags like
`--release` or `--profile`, and the package (in the case of
@@ -399,7 +405,7 @@ The profile for specific packages can be specified with
[`cargo rustc`]: ../commands/cargo-rustc.md
[`cargo test`]: ../commands/cargo-test.md
-### Overrides
+## Overrides
Profile settings can be overridden for specific packages and build-time
crates. To override the settings for a specific package, use the `package`
@@ -451,7 +457,7 @@ match wins):
Overrides cannot specify the `panic`, `lto`, or `rpath` settings.
-#### Overrides and generics
+### Overrides and generics
The location where generic code is instantiated will influence the
optimization settings used for that generic code. This can cause subtle
diff --git a/src/tools/cargo/src/doc/src/reference/publishing.md b/src/tools/cargo/src/doc/src/reference/publishing.md
index 564dfb34e..54a8635fb 100644
--- a/src/tools/cargo/src/doc/src/reference/publishing.md
+++ b/src/tools/cargo/src/doc/src/reference/publishing.md
@@ -1,4 +1,4 @@
-## Publishing on crates.io
+# Publishing on crates.io
Once you've got a library that you'd like to share with the world, it's time to
publish it on [crates.io]! Publishing a crate is when a specific
@@ -8,7 +8,7 @@ Take care when publishing a crate, because a publish is **permanent**. The
version can never be overwritten, and the code cannot be deleted. There is no
limit to the number of versions which can be published, however.
-### Before your first publish
+## Before your first publish
First things first, you’ll need an account on [crates.io] to acquire
an API token. To do so, [visit the home page][crates.io] and log in via a GitHub
@@ -38,7 +38,7 @@ immediately.
> `credentials.toml`. This can be useful if you no longer need it stored on
> the local machine.
-### Before publishing a new crate
+## Before publishing a new crate
Keep in mind that crate names on [crates.io] are allocated on a first-come-first-serve
basis. Once a crate name is taken, it cannot be used for another crate.
@@ -60,7 +60,7 @@ though they are not required.
If you are publishing a library, you may also want to consult the [Rust API
Guidelines].
-#### Packaging a crate
+### Packaging a crate
The next step is to package up your crate and upload it to [crates.io]. For
this we’ll use the [`cargo publish`] subcommand. This command performs the following
@@ -119,7 +119,7 @@ include = [
]
```
-### Uploading the crate
+## Uploading the crate
When you are ready to publish, use the [`cargo publish`] command
to upload to [crates.io]:
@@ -130,19 +130,32 @@ $ cargo publish
And that’s it, you’ve now published your first crate!
-### Publishing a new version of an existing crate
+## Publishing a new version of an existing crate
In order to release a new version, change [the `version` value](manifest.md#the-version-field) specified in your `Cargo.toml` manifest.
Keep in mind [the SemVer rules](semver.md) which provide guidelines on what is a compatible change.
Then run [`cargo publish`] as described above to upload the new version.
-### Managing a crates.io-based crate
+> **Recommendation:** Consider the full release process and automate what you can.
+>
+> Each version should include:
+> - A changelog entry, preferrably [manually curated](https://keepachangelog.com/en/1.0.0/) though a generated one is better than nothing
+> - A [git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) pointing to the published commit
+>
+> Examples of third-party tools that are representative of different workflows include (in alphabetical order):
+> - [cargo-release](https://crates.io/crates/cargo-release)
+> - [cargo-smart-release](https://crates.io/crates/cargo-smart-release)
+> - [release-plz](https://crates.io/crates/release-plz)
+>
+> For more, see [crates.io](https://crates.io/search?q=cargo%20release).
+
+## Managing a crates.io-based crate
Management of crates is primarily done through the command line `cargo` tool
rather than the [crates.io] web interface. For this, there are a few subcommands
to manage a crate.
-#### `cargo yank`
+### `cargo yank`
Occasions may arise where you publish a version of a crate that actually ends up
being broken for one reason or another (syntax error, forgot to include a file,
@@ -166,7 +179,7 @@ goal. Essentially a yank means that all packages with a `Cargo.lock` will not
break, while any future `Cargo.lock` files generated will not list the yanked
version.
-#### `cargo owner`
+### `cargo owner`
A crate is often developed by more than one person, or the primary maintainer
may change over time! The owner of a crate is the only person allowed to publish
@@ -198,7 +211,7 @@ The syntax for teams is currently `github:org:team` (see examples above).
In order to invite a team as an owner one must be a member of that team. No
such restriction applies to removing a team as an owner.
-### GitHub permissions
+## GitHub permissions
Team membership is not something GitHub provides simple public access to, and it
is likely for you to encounter the following message when working with them:
@@ -250,7 +263,7 @@ the “Grant Access” button next to its name:
![Authentication Access Control](../images/auth-level-acl.png)
-#### Troubleshooting GitHub team access errors
+### Troubleshooting GitHub team access errors
When trying to add a GitHub team as crate owner, you may see an error like:
diff --git a/src/tools/cargo/src/doc/src/reference/registries.md b/src/tools/cargo/src/doc/src/reference/registries.md
index 7714a36cd..f0554be98 100644
--- a/src/tools/cargo/src/doc/src/reference/registries.md
+++ b/src/tools/cargo/src/doc/src/reference/registries.md
@@ -1,4 +1,4 @@
-## Registries
+# Registries
Cargo installs crates and fetches dependencies from a "registry". The default
registry is [crates.io]. A registry contains an "index" which contains a
@@ -11,7 +11,11 @@ support publishing new crates directly from Cargo.
If you are implementing a registry server, see [Running a Registry] for more
details about the protocol between Cargo and a registry.
-### Using an Alternate Registry
+If you're using a registry that requires authentication, see [Registry Authentication].
+If you are implementing a credential provider, see [Credential Provider Protocol]
+for details.
+
+## Using an Alternate Registry
To use a registry other than [crates.io], the name and index URL of the
registry must be added to a [`.cargo/config.toml` file][config]. The `registries`
@@ -51,7 +55,7 @@ CARGO_REGISTRIES_MY_REGISTRY_INDEX=https://my-intranet:8080/git/index
> Note: [crates.io] does not accept packages that depend on crates from other
> registries.
-### Publishing to an Alternate Registry
+## Publishing to an Alternate Registry
If the registry supports web API access, then packages can be published
directly to the registry from Cargo. Several of Cargo's commands such as
@@ -100,7 +104,7 @@ has a separate table for each registry, for example:
token = "854DvwSlUwEHtIo3kWy6x7UCPKHfzCmy"
```
-### Registry Protocols
+## Registry Protocols
Cargo supports two remote registry protocols: `git` and `sparse`. If the registry
index URL starts with `sparse+`, Cargo uses the sparse protocol. Otherwise
Cargo uses the `git` protocol.
@@ -117,6 +121,8 @@ controlled via the [`registries.crates-io.protocol`] config key.
[Source Replacement]: source-replacement.md
[Running a Registry]: running-a-registry.md
+[Credential Provider Protocol]: credential-provider-protocol.md
+[Registry Authentication]: registry-authentication.md
[`cargo publish`]: ../commands/cargo-publish.md
[`cargo package`]: ../commands/cargo-package.md
[`cargo login`]: ../commands/cargo-login.md
diff --git a/src/tools/cargo/src/doc/src/reference/registry-authentication.md b/src/tools/cargo/src/doc/src/reference/registry-authentication.md
new file mode 100644
index 000000000..9f8f7e979
--- /dev/null
+++ b/src/tools/cargo/src/doc/src/reference/registry-authentication.md
@@ -0,0 +1,111 @@
+# Registry Authentication
+Cargo authenticates to registries with credential providers. These
+credential providers are external executables or built-in providers that Cargo
+uses to store and retrieve credentials.
+
+Using alternative registries with authentication *requires* a credential provider to be configured
+to avoid unknowingly storing unencrypted credentials on disk. For historical reasons, public
+(non-authenticated) registries do not require credential provider configuration, and the `cargo:token`
+provider is used if no providers are configured.
+
+Cargo also includes platform-specific providers that use the operating system to securely store
+tokens. The `cargo:token` provider is also included which stores credentials in unencrypted plain
+text in the [credentials](config.md#credentials) file.
+
+## Recommended configuration
+It's recommended to configure a global credential provider list in `$CARGO_HOME/config.toml`
+which defaults to:
+* Windows: `%USERPROFILE%\.cargo\config.toml`
+* Unix: `~/.cargo/config.toml`
+
+This recommended configuration uses the operating system provider, with a fallback to `cargo:token`
+to look in Cargo's [credentials](config.md#credentials) file or environment variables.
+
+Some private registries may also recommend a registry-specific credential-provider. Check your
+registry's documentation to see if this is the case.
+
+### macOS configuration
+```toml
+# ~/.cargo/config.toml
+[registry]
+global-credential-providers = ["cargo:token", "cargo:macos-keychain"]
+```
+
+### Linux (libsecret) configuration
+```toml
+# ~/.cargo/config.toml
+[registry]
+global-credential-providers = ["cargo:token", "cargo:libsecret"]
+```
+
+### Windows configuration
+```toml
+# %USERPROFILE%\.cargo\config.toml
+[registry]
+global-credential-providers = ["cargo:token", "cargo:wincred"]
+```
+
+See [`registry.global-credential-providers`](config.md#registryglobal-credential-providers)
+for more details.
+
+## Built-in providers
+Cargo includes several built-in credential providers. The available built-in providers
+may change in future Cargo releases (though there are currently no plans to do so).
+
+### `cargo:token`
+Uses Cargo's [credentials](config.md#credentials) file to store tokens unencrypted in plain text.
+When retrieving tokens, checks the `CARGO_REGISTRIES_<NAME>_TOKEN` environment variable.
+If this credential provider is not listed, then the `*_TOKEN` environment variables will not work.
+
+### `cargo:wincred`
+Uses the Windows Credential Manager to store tokens.
+
+The credentials are stored as `cargo-registry:<index-url>` in the Credential Manager
+under "Windows Credentials".
+
+### `cargo:macos-keychain`
+Uses the macOS Keychain to store tokens.
+
+The Keychain Access app can be used to view stored tokens.
+
+### `cargo:libsecret`
+Uses [libsecret](https://wiki.gnome.org/Projects/Libsecret) to store tokens.
+
+On GNOME, credentials can be viewed using [GNOME Keyring](https://wiki.gnome.org/Projects/GnomeKeyring)
+applications.
+
+### `cargo:token-from-stdout <command> <args>`
+Launch a subprocess that returns a token on stdout. Newlines will be trimmed.
+* The process inherits the user's stdin and stderr.
+* It should exit 0 on success, and nonzero on error.
+* [`cargo login`] and [`cargo logout`] are not supported and return an error if used.
+
+The following environment variables will be provided to the executed command:
+
+* `CARGO` --- Path to the `cargo` binary executing the command.
+* `CARGO_REGISTRY_INDEX_URL` --- The URL of the registry index.
+* `CARGO_REGISTRY_NAME_OPT` --- Optional name of the registry. Should not be used as a lookup key.
+
+Arguments will be passed on to the subcommand.
+
+[`cargo login`]: ../commands/cargo-login.md
+[`cargo logout`]: ../commands/cargo-logout.md
+
+## Credential plugins
+For credential provider plugins that follow Cargo's [credential provider protocol](credential-provider-protocol.md),
+the configuration value should be a string with the path to the executable (or the executable name if on the `PATH`).
+
+For example, to install [cargo-credential-1password](https://crates.io/crates/cargo-credential-1password)
+from crates.io do the following:
+
+Install the provider with `cargo install cargo-credential-1password`
+
+In the config, add to (or create) `registry.global-credential-providers`:
+```toml
+[registry]
+global-credential-providers = ["cargo:token", "cargo-credential-1password --email you@example.com"]
+```
+
+The values in `global-credential-providers` are split on spaces into path and command-line arguments. To
+define a global credential provider where the path or arguments contain spaces, use
+the [`[credential-alias]` table](config.md#credential-alias).
diff --git a/src/tools/cargo/src/doc/src/reference/registry-index.md b/src/tools/cargo/src/doc/src/reference/registry-index.md
index 3eed6ef39..67af8d3cd 100644
--- a/src/tools/cargo/src/doc/src/reference/registry-index.md
+++ b/src/tools/cargo/src/doc/src/reference/registry-index.md
@@ -1,4 +1,4 @@
-## Index Format
+# Index Format
The following defines the format of the index. New features are occasionally
added, which are only understood starting with the version of Cargo that
@@ -6,7 +6,7 @@ introduced them. Older versions of Cargo may not be able to use packages that
make use of new features. However, the format for older packages should not
change, so older versions of Cargo should be able to use them.
-### Index Configuration
+## Index Configuration
The root of the index contains a file named `config.json` which contains JSON
information used by Cargo for accessing the registry. This is an example of
what the [crates.io] config file looks like:
@@ -35,16 +35,21 @@ The keys are:
- `api`: This is the base URL for the web API. This key is optional, but if it
is not specified, commands such as [`cargo publish`] will not work. The web
API is described below.
+- `auth-required`: indicates whether this is a private registry that requires
+ all operations to be authenticated including API requests, crate downloads
+ and sparse index updates.
-### Download Endpoint
+## Download Endpoint
The download endpoint should send the `.crate` file for the requested package.
Cargo supports https, http, and file URLs, HTTP redirects, HTTP1 and HTTP2.
The exact specifics of TLS support depend on the platform that Cargo is
running on, the version of Cargo, and how it was compiled.
+If `auth-required: true` is set in `config.json`, the `Authorization` header
+will be included with http(s) download requests.
-### Index files
+## Index files
The rest of the index repository contains one file for each package, where the
filename is the name of the package in lowercase. Each version of the package
has a separate line in the file. The files are organized in a tier of
@@ -80,7 +85,7 @@ harder to support older versions of Cargo that lack `{prefix}`/`{lowerprefix}`.
For example, nginx rewrite rules can easily construct `{prefix}` but can't
perform case-conversion to construct `{lowerprefix}`.
-### Name restrictions
+## Name restrictions
Registries should consider enforcing limitations on package names added to
their index. Cargo itself allows names with any [alphanumeric], `-`, or `_`
@@ -100,13 +105,13 @@ attacks](https://en.wikipedia.org/wiki/IDN_homograph_attack) and other
concerns in [UTR36](https://www.unicode.org/reports/tr36/) and
[UTS39](https://www.unicode.org/reports/tr39/).
-### Version uniqueness
+## Version uniqueness
Indexes *must* ensure that each version only appears once for each package.
This includes ignoring SemVer build metadata.
For example, the index must *not* contain two entries with a version `1.0.7` and `1.0.7+extra`.
-### JSON schema
+## JSON schema
Each line in a package file contains a JSON object that describes a published
version of the package. The following is a pretty-printed example with comments
@@ -254,19 +259,19 @@ The JSON objects should not be modified after they are added except for the
[Publish API]: registry-web-api.md#publish
[`cargo metadata`]: ../commands/cargo-metadata.md
-### Index Protocols
+## Index Protocols
Cargo supports two remote registry protocols: `git` and `sparse`. The `git` protocol
stores index files in a git repository and the `sparse` protocol fetches individual
files over HTTP.
-#### Git Protocol
+### Git Protocol
The git protocol has no protocol prefix in the index url. For example the git index URL
for [crates.io] is `https://github.com/rust-lang/crates.io-index`.
Cargo caches the git repository on disk so that it can efficiently incrementally fetch
updates.
-#### Sparse Protocol
+### Sparse Protocol
The sparse protocol uses the `sparse+` protocol prefix in the registry URL. For example,
the sparse index URL for [crates.io] is `sparse+https://index.crates.io/`.
@@ -274,24 +279,36 @@ The sparse protocol downloads each index file using an individual HTTP request.
this results in a large number of small HTTP requests, performance is significantly
improved with a server that supports pipelining and HTTP/2.
-##### Caching
+#### Sparse authentication
+Cargo will attempt to fetch the `config.json` file before
+fetching any other files. If the server responds with an HTTP 401, then Cargo will assume
+that the registry requires authentication and re-attempt the request for `config.json`
+with the authentication token included.
+
+On authentication failure (or a missing authentication token) the server may include a
+`www-authenticate` header with a `Cargo login_url="<URL>"` challenge to indicate where the user
+can go to get a token.
+
+Registries that require authentication must set `auth-required: true` in `config.json`.
+
+#### Caching
Cargo caches the crate metadata files, and captures the `ETag` or `Last-Modified`
HTTP header from the server for each entry. When refreshing crate metadata, Cargo
sends the `If-None-Match` or `If-Modified-Since` header to allow the server to respond
with HTTP 304 "Not Modified" if the local cache is valid, saving time and bandwidth.
If both `ETag` and `Last-Modified` headers are present, Cargo uses the `ETag` only.
-##### Cache Invalidation
+#### Cache Invalidation
If a registry is using some kind of CDN or proxy which caches access to the index files,
then it is recommended that registries implement some form of cache invalidation when
the files are updated. If these caches are not updated, then users may not be able to
access new crates until the cache is cleared.
-##### Nonexistent Crates
+#### Nonexistent Crates
For crates that do not exist, the registry should respond with a 404 "Not Found", 410 "Gone"
or 451 "Unavailable For Legal Reasons" code.
-##### Sparse Limitations
+#### Sparse Limitations
Since the URL of the registry is stored in the lockfile, it's not recommended to offer
a registry with both protocols. Discussion about a transition plan is ongoing in issue
[#10964]. The [crates.io] registry is an exception, since Cargo internally substitutes
diff --git a/src/tools/cargo/src/doc/src/reference/registry-web-api.md b/src/tools/cargo/src/doc/src/reference/registry-web-api.md
index 8260028c0..7b0f3511b 100644
--- a/src/tools/cargo/src/doc/src/reference/registry-web-api.md
+++ b/src/tools/cargo/src/doc/src/reference/registry-web-api.md
@@ -1,5 +1,4 @@
-
-## Web API
+# Web API
A registry may host a web API at the location defined in `config.json` to
support any of the actions listed below.
@@ -47,7 +46,7 @@ Cargo sets the following headers for all requests:
2019-01-02)`. This may be modified by the user in a configuration value.
Added in 1.29.
-### Publish
+## Publish
- Endpoint: `/api/v1/crates/new`
- Method: PUT
@@ -184,7 +183,7 @@ A successful response includes the JSON object:
}
```
-### Yank
+## Yank
- Endpoint: `/api/v1/crates/{crate_name}/{version}/yank`
- Method: DELETE
@@ -197,12 +196,12 @@ A successful response includes the JSON object:
```javascript
{
- // Indicates the delete succeeded, always true.
+ // Indicates the yank succeeded, always true.
"ok": true,
}
```
-### Unyank
+## Unyank
- Endpoint: `/api/v1/crates/{crate_name}/{version}/unyank`
- Method: PUT
@@ -215,12 +214,12 @@ A successful response includes the JSON object:
```javascript
{
- // Indicates the delete succeeded, always true.
+ // Indicates the unyank succeeded, always true.
"ok": true,
}
```
-### Owners
+## Owners
Cargo does not have an inherent notion of users and owners, but it does
provide the `owner` command to assist managing who has authorization to
@@ -228,7 +227,7 @@ control a crate. It is up to the registry to decide exactly how users and
owners are handled. See the [publishing documentation] for a description of
how [crates.io] handles owners via GitHub users and teams.
-#### Owners: List
+### Owners: List
- Endpoint: `/api/v1/crates/{crate_name}/owners`
- Method: GET
@@ -255,7 +254,7 @@ A successful response includes the JSON object:
}
```
-#### Owners: Add
+### Owners: Add
- Endpoint: `/api/v1/crates/{crate_name}/owners`
- Method: PUT
@@ -286,7 +285,7 @@ A successful response includes the JSON object:
}
```
-#### Owners: Remove
+### Owners: Remove
- Endpoint: `/api/v1/crates/{crate_name}/owners`
- Method: DELETE
@@ -313,7 +312,7 @@ A successful response includes the JSON object:
}
```
-### Search
+## Search
- Endpoint: `/api/v1/crates`
- Method: GET
@@ -346,7 +345,7 @@ A successful response includes the JSON object:
}
```
-### Login
+## Login
- Endpoint: `/me`
diff --git a/src/tools/cargo/src/doc/src/reference/resolver.md b/src/tools/cargo/src/doc/src/reference/resolver.md
index ffb194c5e..7d01fb167 100644
--- a/src/tools/cargo/src/doc/src/reference/resolver.md
+++ b/src/tools/cargo/src/doc/src/reference/resolver.md
@@ -342,7 +342,7 @@ instead.
[`cargo update`] can be used to update the entries in `Cargo.lock` when new
versions are published. Without any options, it will attempt to update all
packages in the lock file. The `-p` flag can be used to target the update for
-a specific package, and other flags such as `--aggressive` or `--precise` can
+a specific package, and other flags such as `--recursive` or `--precise` can
be used to control how versions are selected.
[`cargo build`]: ../commands/cargo-build.md
@@ -464,10 +464,10 @@ situations may require specifying unusual requirements.
If you fail to do this, it may not be immediately obvious because Cargo can
opportunistically choose the newest version when you run a blanket `cargo
update`. However, if another user depends on your library, and runs `cargo
- update -p your-library`, it will *not* automatically update "bar" if it is
+ update your-library`, it will *not* automatically update "bar" if it is
locked in their `Cargo.lock`. It will only update "bar" in that situation if
the dependency declaration is also updated. Failure to do so can cause
- confusing build errors for the user using `cargo update -p`.
+ confusing build errors for the user using `cargo update your-library`.
* If two packages are tightly coupled, then an `=` dependency requirement may
help ensure that they stay in sync. For example, a library with a companion
proc-macro library will sometimes make assumptions between the two libraries
diff --git a/src/tools/cargo/src/doc/src/reference/running-a-registry.md b/src/tools/cargo/src/doc/src/reference/running-a-registry.md
index 144f1ee6a..87ab08ede 100644
--- a/src/tools/cargo/src/doc/src/reference/running-a-registry.md
+++ b/src/tools/cargo/src/doc/src/reference/running-a-registry.md
@@ -1,4 +1,4 @@
-## Running a Registry
+# Running a Registry
A minimal registry can be implemented by having a git repository that contains
an index, and a server that contains the compressed `.crate` files created by
diff --git a/src/tools/cargo/src/doc/src/reference/semver.md b/src/tools/cargo/src/doc/src/reference/semver.md
index 69d983078..f09250f1a 100644
--- a/src/tools/cargo/src/doc/src/reference/semver.md
+++ b/src/tools/cargo/src/doc/src/reference/semver.md
@@ -2135,9 +2135,16 @@ std = []
#### Possibly-breaking: removing an optional dependency {#cargo-remove-opt-dep}
-Removing an optional dependency can break a project using your library because
+Removing an [optional dependency][opt-dep] can break a project using your library because
another project may be enabling that dependency via [Cargo features].
+When there is an optional dependency, cargo implicitly defines a feature of
+the same name to provide a mechanism to enable the dependency and to check
+when it is enabled. This problem can be avoided by using the `dep:` syntax in
+the `[features]` table, which disables this implicit feature. Using `dep:`
+makes it possible to hide the existence of optional dependencies under more
+semantically-relevant names which can be more safely modified.
+
```toml
# Breaking change example
@@ -2152,7 +2159,33 @@ curl = { version = "0.4.31", optional = true }
# ..curl removed
```
+```toml
+# MINOR CHANGE
+#
+# This example shows how to avoid breaking changes with optional dependencies.
+
+###########################################################
+# Before
+[dependencies]
+curl = { version = "0.4.31", optional = true }
+
+[features]
+networking = ["dep:curl"]
+
+###########################################################
+# After
+[dependencies]
+# Here, one optional dependency was replaced with another.
+hyper = { version = "0.14.27", optional = true }
+
+[features]
+networking = ["dep:hyper"]
+```
+
Mitigation strategies:
+* Use the `dep:` syntax in the `[features]` table to avoid exposing optional
+ dependencies in the first place. See [optional dependencies][opt-dep] for
+ more information.
* Clearly document your features. If the optional dependency is not included
in the documented list of features, then you may decide to consider it safe
to change undocumented entries.
@@ -2166,6 +2199,8 @@ Mitigation strategies:
optional dependencies necessary to implement "networking". Then document the
"networking" feature.
+[opt-dep]: features.md#optional-dependencies
+
#### Minor: changing dependency features {#cargo-change-dep-feature}
It is usually safe to change the features on a dependency, as long as the
diff --git a/src/tools/cargo/src/doc/src/reference/source-replacement.md b/src/tools/cargo/src/doc/src/reference/source-replacement.md
index b8bcdc7ae..520604e5c 100644
--- a/src/tools/cargo/src/doc/src/reference/source-replacement.md
+++ b/src/tools/cargo/src/doc/src/reference/source-replacement.md
@@ -1,4 +1,4 @@
-## Source Replacement
+# Source Replacement
This document is about replacing the crate index. You can read about overriding
dependencies in the [overriding dependencies] section of this
@@ -34,7 +34,7 @@ token for the specified registry.
[overriding dependencies]: overriding-dependencies.md
[registries]: registries.md
-### Configuration
+## Configuration
Configuration of replacement sources is done through [`.cargo/config.toml`][config]
and the full set of available keys are:
@@ -82,7 +82,7 @@ git = "https://example.com/path/to/repo"
[config]: config.md
-### Registry Sources
+## Registry Sources
A "registry source" is one that is the same as crates.io itself. That is, it has
an index served in a git repository which matches the format of the
@@ -92,7 +92,7 @@ then has configuration indicating where to download crates from.
Currently there is not an already-available project for setting up a mirror of
crates.io. Stay tuned though!
-### Local Registry Sources
+## Local Registry Sources
A "local registry source" is intended to be a subset of another registry
source, but available on the local filesystem (aka vendoring). Local registries
@@ -111,7 +111,7 @@ Local registries are contained within one directory and contain a number of
the same format as the crates.io-index project (populated with just entries for
the crates that are present).
-### Directory Sources
+## Directory Sources
A "directory source" is similar to a local registry source where it contains a
number of crates available on the local filesystem, suitable for vendoring
diff --git a/src/tools/cargo/src/doc/src/reference/specifying-dependencies.md b/src/tools/cargo/src/doc/src/reference/specifying-dependencies.md
index f044af95b..746b5fcb2 100644
--- a/src/tools/cargo/src/doc/src/reference/specifying-dependencies.md
+++ b/src/tools/cargo/src/doc/src/reference/specifying-dependencies.md
@@ -1,4 +1,4 @@
-## Specifying Dependencies
+# Specifying Dependencies
Your crates can depend on other libraries from [crates.io] or other
registries, `git` repositories, or subdirectories on your local file system.
@@ -8,7 +8,7 @@ locally. You can have different dependencies for different platforms, and
dependencies that are only used during development. Let's take a look at how
to do each of these.
-### Specifying dependencies from crates.io
+## Specifying dependencies from crates.io
Cargo is configured to look for dependencies on [crates.io] by default. Only
the name and a version string are required in this case. In [the cargo
@@ -23,7 +23,7 @@ The string `"0.1.12"` is a version requirement. Although it looks like a
specific *version* of the `time` crate, it actually specifies a *range* of
versions and allows [SemVer] compatible updates. An update is allowed if the new
version number does not modify the left-most non-zero number in the major, minor,
-patch grouping. In this case, if we ran `cargo update -p time`, cargo should
+patch grouping. In this case, if we ran `cargo update time`, cargo should
update us to version `0.1.13` if it is the latest `0.1.z` release, but would not
update us to `0.2.0`. If instead we had specified the version string as `1.0`,
cargo should update to `1.1` if it is the latest `1.y` release, but not `2.0`.
@@ -53,10 +53,21 @@ and `x > 0`.
It is possible to further tweak the logic for selecting compatible versions
using special operators, though it shouldn't be necessary most of the time.
+## Version requirement syntax
+
### Caret requirements
-**Caret requirements** are an alternative syntax for the default strategy,
-`^1.2.3` is exactly equivalent to `1.2.3`.
+**Caret requirements** are the default version requirement strategy.
+This version strategy allows [SemVer] compatible updates.
+They are specified as version requirements with a leading caret (`^`).
+
+`^1.2.3` is an example of a caret requirement.
+
+Leaving off the caret is a simplified equivalent syntax to using caret requirements.
+While caret requirements are the default, it is recommended to use the
+simplified syntax when possible.
+
+`log = "^1.2.3"` is exactly equivalent to `log = "1.2.3"`.
### Tilde requirements
@@ -102,7 +113,7 @@ Here are some examples of comparison requirements:
= 1.2.3
```
-### Multiple requirements
+### Multiple version requirements
As shown in the examples above, multiple version requirements can be
separated with a comma, e.g., `>= 1.2, < 1.5`.
@@ -144,7 +155,7 @@ separated with a comma, e.g., `>= 1.2, < 1.5`.
[#6584]: https://github.com/rust-lang/cargo/issues/6584
[#10599]: https://github.com/rust-lang/cargo/issues/10599
-### Specifying dependencies from other registries
+## Specifying dependencies from other registries
To specify a dependency from a registry other than [crates.io], first the
registry must be configured in a `.cargo/config.toml` file. See the [registries
@@ -157,11 +168,11 @@ some-crate = { version = "1.0", registry = "my-registry" }
```
> **Note**: [crates.io] does not allow packages to be published with
-> dependencies on other registries.
+> dependencies on code published outside of [crates.io].
[registries documentation]: registries.md
-### Specifying dependencies from `git` repositories
+## Specifying dependencies from `git` repositories
To depend on a library located in a `git` repository, the minimum information
you need to specify is the location of the repository with the `git` key:
@@ -177,8 +188,8 @@ Cargo will fetch the `git` repository at this location then look for a
of a workspace and setting `git` to the repository containing the workspace).
Since we haven’t specified any other information, Cargo assumes that
-we intend to use the latest commit on the default branch branch
-to build our package, which may not necessarily be the main branch.
+we intend to use the latest commit on the default branch to build
+our package, which may not necessarily be the main branch.
You can combine the `git` key with the `rev`, `tag`, or `branch` keys to
specify something else. Here's an example of specifying that you want to use
the latest commit on a branch named `next`:
@@ -202,13 +213,24 @@ once the lock is in place. However, they can be pulled down manually with
See [Git Authentication] for help with git authentication for private repos.
-> **Note**: [crates.io] does not allow packages to be published with `git`
-> dependencies (`git` [dev-dependencies] are ignored). See the [Multiple
-> locations](#multiple-locations) section for a fallback alternative.
+> **Note**: Neither the `git` key nor the `path` key changes the meaning of the
+> `version` key: the `version` key always implies that the package is available
+> in a registry. `version`, `git`, and `path` keys are considered [separate
+> locations](#multiple-locations) for resolving the dependency.
+>
+> When the dependency is retrieved from `git`, the `version` key will _not_
+> affect which commit is used, but the version information in the dependency's
+> `Cargo.toml` file will still be validated against the `version` requirement.
+
+> **Note**: [crates.io] does not allow packages to be published with
+> dependencies on code published outside of [crates.io] itself
+> ([dev-dependencies] are ignored). See the [Multiple
+> locations](#multiple-locations) section for a fallback alternative for `git`
+> and `path` dependencies.
[Git Authentication]: ../appendix/git-authentication.md
-### Specifying path dependencies
+## Specifying path dependencies
Over time, our `hello_world` package from [the guide](../guide/index.md) has
grown significantly in size! It’s gotten to the point that we probably want to
@@ -245,11 +267,18 @@ and specify its version in the dependencies line as well:
hello_utils = { path = "hello_utils", version = "0.1.0" }
```
-> **Note**: [crates.io] does not allow packages to be published with `path`
-> dependencies (`path` [dev-dependencies] are ignored). See the [Multiple
-> locations](#multiple-locations) section for a fallback alternative.
+> **Note**: Neither the `git` key nor the `path` key changes the meaning of the
+> `version` key: the `version` key always implies that the package is available
+> in a registry. `version`, `git`, and `path` keys are considered [separate
+> locations](#multiple-locations) for resolving the dependency.
+
+> **Note**: [crates.io] does not allow packages to be published with
+> dependencies on code published outside of [crates.io] itself
+> ([dev-dependencies] are ignored). See the [Multiple
+> locations](#multiple-locations) section for a fallback alternative for `git`
+> and `path` dependencies.
-### Multiple locations
+## Multiple locations
It is possible to specify both a registry version and a `git` or `path`
location. The `git` or `path` dependency will be used locally (in which case
@@ -278,7 +307,7 @@ is published. This is similar to specifying an
[override](overriding-dependencies.md), but only applies to this one
dependency declaration.
-### Platform specific dependencies
+## Platform specific dependencies
Platform-specific dependencies take the same format, but are listed under a
`target` section. Normally Rust-like [`#[cfg]`
@@ -337,7 +366,7 @@ winhttp = "0.4.0"
openssl = "1.0.1"
```
-#### Custom target specifications
+### Custom target specifications
If you’re using a custom target specification (such as `--target
foo/bar.json`), use the base filename without the `.json` extension:
@@ -353,7 +382,7 @@ native = { path = "native/i686" }
> **Note**: Custom target specifications are not usable on the stable channel.
-### Development dependencies
+## Development dependencies
You can add a `[dev-dependencies]` section to your `Cargo.toml` whose format
is equivalent to `[dependencies]`:
@@ -385,7 +414,7 @@ mio = "0.0.1"
> packagers) may want to run tests within a crate, so providing a `version` if
> possible can still be beneficial.
-### Build dependencies
+## Build dependencies
You can depend on other Cargo-based crates for use in your build scripts.
Dependencies are declared through the `build-dependencies` section of the
@@ -417,7 +446,7 @@ itself and its build script are built separately, so their
dependencies need not coincide. Cargo is kept simpler and cleaner by
using independent dependencies for independent purposes.
-### Choosing features
+## Choosing features
If a package you depend on offers conditional features, you can
specify which to use:
@@ -433,7 +462,7 @@ features = ["secure-password", "civet"]
More information about features can be found in the [features
chapter](features.md#dependency-features).
-### Renaming dependencies in `Cargo.toml`
+## Renaming dependencies in `Cargo.toml`
When writing a `[dependencies]` section in `Cargo.toml` the key you write for a
dependency typically matches up to the name of the crate you import from in the
@@ -492,7 +521,7 @@ following to the above manifest:
log-debug = ['bar/log-debug'] # using 'foo/log-debug' would be an error!
```
-### Inheriting a dependency from a workspace
+## Inheriting a dependency from a workspace
Dependencies can be inherited from a workspace by specifying the
dependency in the workspace's [`[workspace.dependencies]`][workspace.dependencies] table.
diff --git a/src/tools/cargo/src/doc/src/reference/timings.md b/src/tools/cargo/src/doc/src/reference/timings.md
index b978d52cd..e8ff751ca 100644
--- a/src/tools/cargo/src/doc/src/reference/timings.md
+++ b/src/tools/cargo/src/doc/src/reference/timings.md
@@ -10,7 +10,7 @@ This writes an HTML report in `target/cargo-timings/cargo-timing.html`. This
also writes a copy of the report to the same directory with a timestamp in the
filename, if you want to look at older runs.
-#### Reading the graphs
+## Reading the graphs
There are two tables and two graphs in the output.
diff --git a/src/tools/cargo/src/doc/src/reference/unstable.md b/src/tools/cargo/src/doc/src/reference/unstable.md
index 55084f88e..c8047de90 100644
--- a/src/tools/cargo/src/doc/src/reference/unstable.md
+++ b/src/tools/cargo/src/doc/src/reference/unstable.md
@@ -1,4 +1,4 @@
-## Unstable Features
+# Unstable Features
Experimental Cargo features are only available on the [nightly channel]. You
are encouraged to experiment with these features to see if they meet your
@@ -59,7 +59,7 @@ For the latest nightly, see the [nightly version] of this page.
[stabilized]: https://doc.crates.io/contrib/process/unstable.html#stabilization
[nightly version]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#script
-### List of unstable features
+## List of unstable features
* Unstable-specific features
* [-Z allow-features](#allow-features) --- Provides a way to restrict which unstable features are used.
@@ -82,7 +82,6 @@ For the latest nightly, see the [nightly version] of this page.
* [build-std-features](#build-std-features) --- Sets features to use with the standard library.
* [binary-dep-depinfo](#binary-dep-depinfo) --- Causes the dep-info file to track binary dependencies.
* [panic-abort-tests](#panic-abort-tests) --- Allows running tests with the "abort" panic strategy.
- * [keep-going](#keep-going) --- Build as much as possible rather than aborting on the first error.
* [check-cfg](#check-cfg) --- Compile-time validation of `cfg` expressions.
* [host-config](#host-config) --- Allows setting `[target]`-like configuration settings for host build targets.
* [target-applies-to-host](#target-applies-to-host) --- Alters whether certain flags will be passed to host build targets.
@@ -94,7 +93,6 @@ For the latest nightly, see the [nightly version] of this page.
* [codegen-backend](#codegen-backend) --- Select the codegen backend used by rustc.
* [per-package-target](#per-package-target) --- Sets the `--target` to use for each individual package.
* [artifact dependencies](#artifact-dependencies) --- Allow build artifacts to be included into other build artifacts and build them for different targets.
- * [`[lints]`](#lints) --- Configure lint levels for various linter tools.
* Information and metadata
* [Build-plan](#build-plan) --- Emits JSON information on which commands will be run.
* [unit-graph](#unit-graph) --- Emits JSON for Cargo's internal graph structure.
@@ -103,14 +101,13 @@ For the latest nightly, see the [nightly version] of this page.
* [config-include](#config-include) --- Adds the ability for config files to include other files.
* [`cargo config`](#cargo-config) --- Adds a new subcommand for viewing config files.
* Registries
- * [credential-process](#credential-process) --- Adds support for fetching registry tokens from an external authentication program.
* [publish-timeout](#publish-timeout) --- Controls the timeout between uploading the crate and being available in the index
- * [registry-auth](#registry-auth) --- Adds support for authenticated registries, and generate registry authentication tokens using asymmetric cryptography.
+ * [asymmetric-token](#asymmetric-token) --- Adds support for authentication tokens using asymmetric cryptography (`cargo:paseto` provider).
* Other
* [gitoxide](#gitoxide) --- Use `gitoxide` instead of `git2` for a set of operations.
* [script](#script) --- Enable support for single-file `.rs` packages.
-### allow-features
+## allow-features
This permanently-unstable flag makes it so that only a listed set of
unstable features can be used. Specifically, if you pass
@@ -136,7 +133,7 @@ to any Rust tools that cargo ends up calling (like `rustc` or
`rustdoc`). Thus, if you run `cargo -Zallow-features=`, no unstable
Cargo _or_ Rust features can be used.
-### no-index-update
+## no-index-update
* Original Issue: [#3479](https://github.com/rust-lang/cargo/issues/3479)
* Tracking Issue: [#7404](https://github.com/rust-lang/cargo/issues/7404)
@@ -145,7 +142,7 @@ the registry index. This is intended for tools such as Crater that issue many
Cargo commands, and you want to avoid the network latency for updating the
index each time.
-### mtime-on-use
+## mtime-on-use
* Original Issue: [#6477](https://github.com/rust-lang/cargo/pull/6477)
* Cache usage meta tracking issue: [#7150](https://github.com/rust-lang/cargo/issues/7150)
@@ -156,7 +153,7 @@ To make this more practical setting the `unstable.mtime_on_use` flag in `.cargo/
or the corresponding ENV variable will apply the `-Z mtime-on-use` to all
invocations of nightly cargo. (the config flag is ignored by stable)
-### avoid-dev-deps
+## avoid-dev-deps
* Original Issue: [#4988](https://github.com/rust-lang/cargo/issues/4988)
* Tracking Issue: [#5133](https://github.com/rust-lang/cargo/issues/5133)
@@ -166,7 +163,7 @@ used. The `-Z avoid-dev-deps` flag allows Cargo to avoid downloading
dev-dependencies if they are not needed. The `Cargo.lock` file will not be
generated if dev-dependencies are skipped.
-### minimal-versions
+## minimal-versions
* Original Issue: [#4100](https://github.com/rust-lang/cargo/issues/4100)
* Tracking Issue: [#5657](https://github.com/rust-lang/cargo/issues/5657)
@@ -186,7 +183,7 @@ minimum versions that you are actually using. That is, if Cargo.toml says
`foo = "1.0.0"` that you don't accidentally depend on features added only in
`foo 1.5.0`.
-### direct-minimal-versions
+## direct-minimal-versions
* Original Issue: [#4100](https://github.com/rust-lang/cargo/issues/4100)
* Tracking Issue: [#5657](https://github.com/rust-lang/cargo/issues/5657)
@@ -203,7 +200,7 @@ minimum versions that you are actually using. That is, if Cargo.toml says
Indirect dependencies are resolved as normal so as not to be blocked on their
minimal version validation.
-### out-dir
+## out-dir
* Original Issue: [#4875](https://github.com/rust-lang/cargo/issues/4875)
* Tracking Issue: [#6790](https://github.com/rust-lang/cargo/issues/6790)
@@ -226,7 +223,7 @@ This can also be specified in `.cargo/config.toml` files.
out-dir = "out"
```
-### doctest-xcompile
+## doctest-xcompile
* Tracking Issue: [#7040](https://github.com/rust-lang/cargo/issues/7040)
* Tracking Rustc Issue: [#64245](https://github.com/rust-lang/rust/issues/64245)
@@ -242,7 +239,7 @@ information from `.cargo/config.toml`. See the rustc issue for more information.
cargo test --target foo -Zdoctest-xcompile
```
-### Build-plan
+## Build-plan
* Tracking Issue: [#5579](https://github.com/rust-lang/cargo/issues/5579)
The `--build-plan` argument for the `build` command will output JSON with
@@ -254,7 +251,7 @@ Example:
cargo +nightly build --build-plan -Z unstable-options
```
-### Metabuild
+## Metabuild
* Tracking Issue: [rust-lang/rust#49803](https://github.com/rust-lang/rust/issues/49803)
* RFC: [#2196](https://github.com/rust-lang/rfcs/blob/master/text/2196-metabuild.md)
@@ -287,7 +284,7 @@ extra-info = "qwerty"
Metabuild packages should have a public function called `metabuild` that
performs the same actions as a regular `build.rs` script would perform.
-### public-dependency
+## public-dependency
* Tracking Issue: [#44663](https://github.com/rust-lang/rust/issues/44663)
The 'public-dependency' feature allows marking dependencies as 'public'
@@ -304,7 +301,7 @@ my_dep = { version = "1.2.3", public = true }
private_dep = "2.0.0" # Will be 'private' by default
```
-### msrv-policy
+## msrv-policy
- [#9930](https://github.com/rust-lang/cargo/issues/9930) (MSRV-aware resolver)
- [#10653](https://github.com/rust-lang/cargo/issues/10653) (MSRV-aware cargo-add)
- [#10903](https://github.com/rust-lang/cargo/issues/10903) (MSRV-aware cargo-install)
@@ -312,7 +309,7 @@ private_dep = "2.0.0" # Will be 'private' by default
The `msrv-policy` feature enables experiments in MSRV-aware policy for cargo in
preparation for an upcoming RFC.
-### build-std
+## build-std
* Tracking Repository: <https://github.com/rust-lang/wg-cargo-std-aware>
The `build-std` feature enables Cargo to compile the standard library itself as
@@ -367,7 +364,7 @@ $ cargo +nightly build -Z build-std=core,alloc
The value here is a comma-separated list of standard library crates to build.
-#### Requirements
+### Requirements
As a summary, a list of requirements today to use `-Z build-std` are:
@@ -376,7 +373,7 @@ As a summary, a list of requirements today to use `-Z build-std` are:
* You must use both a nightly Cargo and a nightly rustc
* The `-Z build-std` flag must be passed to all `cargo` invocations.
-#### Reporting bugs and helping out
+### Reporting bugs and helping out
The `-Z build-std` feature is in the very early stages of development! This
feature for Cargo has an extremely long history and is very large in scope, and
@@ -393,7 +390,7 @@ something doesn't quite work the way you'd like it to, feel free to check out
the [issue tracker](https://github.com/rust-lang/wg-cargo-std-aware/issues) of
the tracking repository, and if it's not there please file a new issue!
-### build-std-features
+## build-std-features
* Tracking Repository: <https://github.com/rust-lang/wg-cargo-std-aware>
This flag is a sibling to the `-Zbuild-std` feature flag. This will configure
@@ -402,7 +399,7 @@ library. The default enabled features, at this time, are `backtrace` and
`panic-unwind`. This flag expects a comma-separated list and, if provided, will
override the default list of features enabled.
-### binary-dep-depinfo
+## binary-dep-depinfo
* Tracking rustc issue: [#63012](https://github.com/rust-lang/rust/issues/63012)
The `-Z binary-dep-depinfo` flag causes Cargo to forward the same flag to
@@ -413,7 +410,7 @@ the crate will be rebuilt). The primary use case is for building the compiler
itself, which has implicit dependencies on the standard library that would
otherwise be untracked for change-detection.
-### panic-abort-tests
+## panic-abort-tests
* Tracking Issue: [#67650](https://github.com/rust-lang/rust/issues/67650)
* Original Pull Request: [#7460](https://github.com/rust-lang/cargo/pull/7460)
@@ -429,37 +426,7 @@ like to stabilize it somehow!
[rust-lang/rust#64158]: https://github.com/rust-lang/rust/pull/64158
-### keep-going
-* Tracking Issue: [#10496](https://github.com/rust-lang/cargo/issues/10496)
-
-`cargo build --keep-going` (and similarly for every command involving compilation, like `check` and `doc`)
-will build as many crates in the dependency graph as possible,
-rather than aborting the build at the first one that fails to build.
-
-For example if the current package depends on dependencies `fails` and `works`,
-one of which fails to build, `cargo check -j1` may or may not build the one that
-succeeds (depending on which one of the two builds Cargo picked to run first),
-whereas `cargo check -j1 --keep-going` would definitely run both builds, even if
-the one run first fails.
-
-The `-Z unstable-options` command-line option must be used in order to use
-`--keep-going` while it is not yet stable:
-
-```console
-cargo check --keep-going -Z unstable-options
-```
-
-While `cargo test` and `cargo bench` commands involve compilation, they do not provide a `--keep-going` flag.
-Both commands already include a similar `--no-fail-fast` flag, allowing running as many tests as possible without stopping at the first failure.
-To "compile" as many tests as possible, use target selection flags like `--tests` to build test binaries separately.
-For example,
-
-```console
-cargo build --tests --keep-going -Zunstable-options
-cargo test --tests --no-fail-fast
-```
-
-### config-include
+## config-include
* Tracking Issue: [#7723](https://github.com/rust-lang/cargo/issues/7723)
This feature requires the `-Zconfig-include` command-line option.
@@ -487,7 +454,7 @@ different. When a config file contains an `include` key:
2. Then, the config file's own values are merged on top of the config
from the `include` path.
-### target-applies-to-host
+## target-applies-to-host
* Original Pull Request: [#9322](https://github.com/rust-lang/cargo/pull/9322)
* Tracking Issue: [#9453](https://github.com/rust-lang/cargo/issues/9453)
@@ -529,7 +496,7 @@ target-applies-to-host = false
cargo +nightly -Ztarget-applies-to-host build --target x86_64-unknown-linux-gnu
```
-### host-config
+## host-config
* Original Pull Request: [#9322](https://github.com/rust-lang/cargo/pull/9322)
* Tracking Issue: [#9452](https://github.com/rust-lang/cargo/issues/9452)
@@ -564,7 +531,7 @@ Setting `-Zhost-config` changes the default for `target-applies-to-host` to
cargo +nightly -Ztarget-applies-to-host -Zhost-config build --target x86_64-unknown-linux-gnu
```
-### unit-graph
+## unit-graph
* Tracking Issue: [#8002](https://github.com/rust-lang/cargo/issues/8002)
The `--unit-graph` flag can be passed to any build command (`build`, `check`,
@@ -698,7 +665,7 @@ The following is a description of the JSON structure:
}
```
-### Profile `rustflags` option
+## Profile `rustflags` option
* Original Issue: [rust-lang/cargo#7878](https://github.com/rust-lang/cargo/issues/7878)
* Tracking Issue: [rust-lang/cargo#10271](https://github.com/rust-lang/cargo/issues/10271)
@@ -728,7 +695,7 @@ profile-rustflags = true
rustflags = [ "-C", "..." ]
```
-### rustdoc-map
+## rustdoc-map
* Tracking Issue: [#8296](https://github.com/rust-lang/cargo/issues/8296)
This feature adds configuration settings that are passed to `rustdoc` so that
@@ -769,7 +736,7 @@ The default value is `"remote"`.
The value may also take a URL for a custom location.
-### per-package-target
+## per-package-target
* Tracking Issue: [#9406](https://github.com/rust-lang/cargo/pull/9406)
* Original Pull Request: [#9030](https://github.com/rust-lang/cargo/pull/9030)
* Original Issue: [#7004](https://github.com/rust-lang/cargo/pull/7004)
@@ -792,7 +759,7 @@ In this example, the crate is always built for
as a plugin for a main program that runs on the host (or provided on
the command line) target.
-### artifact-dependencies
+## artifact-dependencies
* Tracking Issue: [#9096](https://github.com/rust-lang/cargo/pull/9096)
* Original Pull Request: [#9992](https://github.com/rust-lang/cargo/pull/9992)
@@ -802,7 +769,7 @@ and use the artifacts built by those crates at compile time.
Run `cargo` with `-Z bindeps` to enable this functionality.
-#### artifact-dependencies: Dependency declarations
+### artifact-dependencies: Dependency declarations
Artifact-dependencies adds the following keys to a dependency declaration in `Cargo.toml`:
@@ -854,7 +821,7 @@ Artifact-dependencies adds the following keys to a dependency declaration in `Ca
same-target = { version = "1.0", artifact = "bin", target = "target" }
```
-#### artifact-dependencies: Environment variables
+### artifact-dependencies: Environment variables
After building an artifact dependency, Cargo provides the following environment variables that you can use to access the artifact:
@@ -883,9 +850,9 @@ For each kind of dependency, these variables are supplied to the same part of th
[`env!`]: https://doc.rust-lang.org/std/macro.env.html
-#### artifact-dependencies: Examples
+### artifact-dependencies: Examples
-##### Example: use a binary executable from a build script
+#### Example: use a binary executable from a build script
In the `Cargo.toml` file, you can specify a dependency on a binary to make available for a build script:
@@ -910,7 +877,7 @@ fn main() {
}
```
-##### Example: use _cdylib_ artifact in build script
+#### Example: use _cdylib_ artifact in build script
The `Cargo.toml` in the consuming package, building the `bar` library as `cdylib`
for a specific build target…
@@ -928,7 +895,7 @@ fn main() {
}
```
-##### Example: use _binary_ artifact and its library in a binary
+#### Example: use _binary_ artifact and its library in a binary
The `Cargo.toml` in the consuming package, building the `bar` binary for inclusion
as artifact while making it available as library as well…
@@ -947,7 +914,7 @@ fn main() {
}
```
-### publish-timeout
+## publish-timeout
* Tracking Issue: [11222](https://github.com/rust-lang/cargo/issues/11222)
The `publish.timeout` key in a config file can be used to control how long
@@ -965,35 +932,11 @@ It requires the `-Zpublish-timeout` command-line options to be set.
timeout = 300 # in seconds
```
-### registry-auth
-* Tracking Issue: [10474](https://github.com/rust-lang/cargo/issues/10474)
-* RFC: [#3139](https://github.com/rust-lang/rfcs/pull/3139)
-
-Enables Cargo to include the authorization token for API requests, crate downloads
-and sparse index updates by adding a configuration option to config.json
-in the registry index.
-
-To use this feature, the registry server must include `"auth-required": true` in
-`config.json`, and you must pass the `-Z registry-auth` flag on the Cargo command line.
-
-When using the sparse protocol, Cargo will attempt to fetch the `config.json` file before
-fetching any other files. If the server responds with an HTTP 401, then Cargo will assume
-that the registry requires authentication and re-attempt the request for `config.json`
-with the authentication token included.
-
-On authentication failure (or missing authentication token) the server MAY include a
-`WWW-Authenticate` header with a `Cargo login_url` challenge to indicate where the user
-can go to get a token.
-
-```
-WWW-Authenticate: Cargo login_url="https://test-registry-login/me
-```
-
-This same flag is also used to enable asymmetric authentication tokens.
+## asymmetric-token
* Tracking Issue: [10519](https://github.com/rust-lang/cargo/issues/10519)
* RFC: [#3231](https://github.com/rust-lang/rfcs/pull/3231)
-Add support for Cargo to authenticate the user to registries without sending secrets over the network.
+The `-Z asymmetric-token` flag enables the `cargo:paseto` credential provider which allows Cargo to authenticate to registries without sending secrets over the network.
In [`config.toml`](config.md) and `credentials.toml` files there is a field called `private-key`, which is a private key formatted in the secret [subset of `PASERK`](https://github.com/paseto-standard/paserk/blob/master/types/secret.md) and is used to sign asymmetric tokens
@@ -1029,266 +972,7 @@ The "footer" (which is part of the signature) will be a JSON string in UTF-8 and
PASETO includes the message that was signed, so the server does not have to reconstruct the exact string from the request in order to check the signature. The server does need to check that the signature is valid for the string in the PASETO and that the contents of that string matches the request.
If a claim should be expected for the request but is missing in the PASETO then the request must be rejected.
-### credential-process
-* Tracking Issue: [#8933](https://github.com/rust-lang/cargo/issues/8933)
-* RFC: [#2730](https://github.com/rust-lang/rfcs/pull/2730)
-
-The `credential-process` feature adds a config setting to fetch registry
-authentication tokens by calling an external process.
-
-To use this feature, you must pass the `-Z credential-process` flag on the
-command-line.
-
-#### `credential-process` Configuration
-
-To configure which process to run to fetch the token, specify the process in
-the `registry` table in a [config file] with spaces separating arguments. If the
-path to the provider or its arguments contain spaces, then it mused be defined in
-the `credential-alias` table and referenced instead.
-
-```toml
-[registry]
-global-credential-providers = ["/usr/bin/cargo-creds"]
-```
-
-The provider at the end of the list will be attempted first. This ensures
-that when config files are merged, files closer to the project (and ultimatly
-environment variables) have precedence.
-
-In this example, the `my-provider` provider will be attempted first, and if
-it cannot provide credentials, then the `cargo:token` provider will be used.
-
-```toml
-[registry]
-global-credential-providers = ['cargo:token', 'my-provider']
-```
-
-If you want to use a different provider for a specific registry, it can be
-specified in the `registries` table:
-
-```toml
-[registries.my-registry]
-credential-provider = "/usr/bin/cargo-creds"
-```
-
-The credential provider for crates.io can be specified as:
-
-```toml
-[registry]
-credential-provider = "/usr/bin/cargo-creds"
-```
-
-The value can be a string with spaces separating arguments or it can be a TOML
-array of strings.
-
-For commonly-used providers, or providers that need to contain spaces in the arguments
-or path, the `credential-alias` table can be used. These aliases can be referenced
-in `credential-provider` or `global-credential-providers`.
-
-```toml
-[credential-alias]
-my-alias = ["/usr/bin/cargo-creds", "--argument"]
-
-[registry]
-global-credential-providers = ["cargo:token", "my-alias"]
-```
-
-#### Built-in providers
-
-Cargo now includes several built-in credential providers. These providers are
-executed within the Cargo process. They are identified with the `cargo:` prefix.
-
-* `cargo:token` - Uses Cargo's config and `credentials.toml` to store the token (default).
-* `cargo:wincred` - Uses the Windows Credential Manager to store the token.
-* `cargo:macos-keychain` - Uses the macOS Keychain to store the token.
-* `cargo:libsecret` - Uses [libsecret](https://wiki.gnome.org/Projects/Libsecret) to store tokens on Linux systems.
-* `cargo:token-from-stdout <command>` - Launch a subprocess that returns a token
- on stdout. Newlines will be trimmed. The process inherits the user's stdin and stderr.
- It should exit 0 on success, and nonzero on error.
-
- With this form, [`cargo login`] and [`cargo logout`] are not supported and
- return an error if used.
-
- The following environment variables will be provided to the executed command:
-
- * `CARGO` --- Path to the `cargo` binary executing the command.
- * `CARGO_REGISTRY_INDEX_URL` --- The URL of the registry index.
- * `CARGO_REGISTRY_NAME_OPT` --- Optional name of the registry. Should not be used as a storage key. Not always available.
-
-* `cargo:paseto` - implements asymmetric token support (RFC3231) as a credential provider.
-
-
-`cargo-credential-1password` uses the 1password `op` CLI to store the token. You must
-install the `op` CLI from the [1password
-website](https://1password.com/downloads/command-line/). You must run `op
-signin` at least once with the appropriate arguments (such as `op signin
-my.1password.com user@example.com`), unless you provide the sign-in-address
-and email arguments. The master password will be required on each request
-unless the appropriate `OP_SESSION` environment variable is set. It supports
-the following command-line arguments:
-* `--account`: The account shorthand name to use.
-* `--vault`: The vault name to use.
-* `--sign-in-address`: The sign-in-address, which is a web address such as `my.1password.com`.
-* `--email`: The email address to sign in with.
-
-Install the provider with `cargo install cargo-credential-1password`
-In the config, add it to `global-credential-providers`:
-```toml
-[registry]
-global-credential-providers = ["cargo-credential-1password"]
-```
-
-#### JSON Interface
-When using an external credential provider, Cargo communicates with the credential
-provider using stdin/stdout messages passed as a single line of JSON.
-
-Cargo will always execute the credential provider with the `--cargo-plugin` argument.
-This enables a credential provider executable to have additional functionality beyond
-how Cargo uses it.
-
-The messages here have additional newlines added for readability.
-Actual messages must not contain newlines.
-
-##### Credential hello
-* Sent by: credential provider
-* Purpose: used to identify the supported protocols on process startup
-```javascript
-{
- "v":[1]
-}
-```
-
-##### Login request
-* Sent by: Cargo
-* Purpose: collect and store credentials
-```javascript
-{
- // Protocol version
- "v":1,
- // Action to perform: login
- "kind":"login",
- // Registry information
- "registry":{"index-url":"sparse+https://registry-url/index/", "name": "my-registry"},
-}
-```
-
-##### Read request
-* Sent by: Cargo
-* Purpose: Get the credential for reading crate information
-```javascript
-{
- // Protocol version
- "v":1,
- // Request kind: get credentials
- "kind":"get",
- // Action to perform: read crate information
- "operation":"read",
- // Registry information
- "registry":{"index-url":"sparse+https://registry-url/index/", "name": "my-registry"},
- // Additional command-line args
- "args":[]
-}
-```
-
-##### Publish request
-* Sent by: Cargo
-* Purpose: Get the credential for publishing a crate
-```javascript
-{
- // Protocol version
- "v":1,
- // Request kind: get credentials
- "kind":"get",
- // Action to perform: publish crate
- "operation":"publish",
- // Crate name
- "name":"sample",
- // Crate version
- "vers":"0.1.0",
- // Crate checksum
- "cksum":"...",
- // Registry information
- "registry":{"index-url":"sparse+https://registry-url/index/", "name": "my-registry"},
- // Additional command-line args
- "args":[]
-}
-```
-
-##### Success response
-* Sent by: credential process
-* Purpose: Gives the credential to Cargo
-```javascript
-{"Ok":{
- // Response kind: this was a get request kind
- "kind":"get",
- // Token to send to the registry
- "token":"...",
- // Cache control. Can be one of the following:
- // * "never"
- // * "session"
- // * { "expires": UNIX timestamp }
- "cache":{"expires":1684251794},
- // Is the token operation independent?
- "operation_independent":true
-}}
-```
-
-##### Failure response
-* Sent by: credential process
-* Purpose: Gives error information to Cargo
-```javascript
-{"Err":{
- // Error: the credential provider does not support the
- // registry
- "kind":"url-not-supported",
-
- // Error: The credential could not be found in the provider.
- // using `cargo login --registry ...`.
- "kind":"not-found",
-
- // Error: something else has failed
- "kind":"other",
- "detail": "free form string error message"
-}}
-```
-
-##### Example communication to request a token for reading:
-1. Cargo spawns the credential process, capturing stdin and stdout.
-2. Credential process sends the Hello message to Cargo
- ```javascript
- { "v": [1] }
- ```
-3. Cargo sends the CredentialRequest message to the credential process (newlines added for readability).
- ```javascript
- {
- "v": 1,
- "kind": "get",
- "operation": "read",
- "registry":{"index-url":"sparse+https://registry-url/index/", "name":"ado2"},
- "args":[]
- }
- ```
-4. Credential process sends the CredentialResponse to Cargo (newlines added for readability).
- ```javascript
- {
- "token": "...",
- "cache": "session",
- "operation_independent": false
- }
- ```
-5. Credential process exits
-6. Cargo uses the token for the remainder of the session (until Cargo exits) when interacting with this registry.
-
-[`cargo login`]: ../commands/cargo-login.md
-[`cargo logout`]: ../commands/cargo-logout.md
-[`cargo publish`]: ../commands/cargo-publish.md
-[`cargo owner`]: ../commands/cargo-owner.md
-[`cargo yank`]: ../commands/cargo-yank.md
-[`credentials.toml` file]: config.md#credentials
-[crates.io]: https://crates.io/
-[config file]: config.md
-
-### `cargo config`
+## `cargo config`
* Original Issue: [#2362](https://github.com/rust-lang/cargo/issues/2362)
* Tracking Issue: [#9301](https://github.com/rust-lang/cargo/issues/9301)
@@ -1304,7 +988,7 @@ cargo +nightly -Zunstable-options config get build.rustflags
If no config value is included, it will display all config values. See the
`--help` output for more options available.
-### rustc `--print`
+## rustc `--print`
* Tracking Issue: [#9357](https://github.com/rust-lang/cargo/issues/9357)
@@ -1319,7 +1003,7 @@ The primary use case is to run `cargo rustc --print=cfg` to get config values
for the appropriate target and influenced by any other RUSTFLAGS.
-### Different binary name
+## Different binary name
* Tracking Issue: [#9778](https://github.com/rust-lang/cargo/issues/9778)
* PR: [#9627](https://github.com/rust-lang/cargo/pull/9627)
@@ -1346,7 +1030,7 @@ filename = "007bar"
path = "src/main.rs"
```
-### scrape-examples
+## scrape-examples
* RFC: [#3123](https://github.com/rust-lang/rfcs/pull/3123)
* Tracking Issue: [#9910](https://github.com/rust-lang/cargo/issues/9910)
@@ -1390,7 +1074,7 @@ For example, you can set `doc-scrape-examples` to true for one example target, a
you are ok with dev-deps being build for `cargo doc`.
-### check-cfg
+## check-cfg
* RFC: [#3013](https://github.com/rust-lang/rfcs/pull/3013)
* Tracking Issue: [#10554](https://github.com/rust-lang/cargo/issues/10554)
@@ -1425,7 +1109,7 @@ println!("cargo:rustc-check-cfg=names(foo, bar)");
cargo check -Z unstable-options -Z check-cfg=output
```
-#### `cargo:rustc-check-cfg=CHECK_CFG`
+### `cargo:rustc-check-cfg=CHECK_CFG`
The `rustc-check-cfg` instruction tells Cargo to pass the given value to the
`--check-cfg` flag to the compiler. This may be used for compile-time
@@ -1437,7 +1121,7 @@ with a warning.
If you want to integrate with Cargo features, use `-Zcheck-cfg=features` instead of
trying to do it manually with this option.
-### codegen-backend
+## codegen-backend
The `codegen-backend` feature makes it possible to select the codegen backend used by rustc using a profile.
@@ -1466,7 +1150,7 @@ codegen-backend = true
codegen-backend = "cranelift"
```
-### gitoxide
+## gitoxide
* Tracking Issue: [#11813](https://github.com/rust-lang/cargo/issues/11813)
@@ -1493,7 +1177,7 @@ Valid operations are the following:
* When the unstable feature is on, fetching/cloning a git repository is always a shallow fetch. This roughly equals to `git fetch --depth 1` everywhere.
* Even with the presence of `Cargo.lock` or specifying a commit `{ rev = "…" }`, gitoxide is still smart enough to shallow fetch without unshallowing the existing repository.
-### script
+## script
* Tracking Issue: [#12207](https://github.com/rust-lang/cargo/issues/12207)
@@ -1507,13 +1191,12 @@ fn main() {}
```
A user may optionally specify a manifest in a `cargo` code fence in a module-level comment, like:
-```rust
+````rust
#!/usr/bin/env -S cargo +nightly -Zscript
-
-//! ```cargo
-//! [dependencies]
-//! clap = { version = "4.2", features = ["derive"] }
-//! ```
+```cargo
+[dependencies]
+clap = { version = "4.2", features = ["derive"] }
+```
use clap::Parser;
@@ -1528,9 +1211,9 @@ fn main() {
let args = Args::parse();
println!("{:?}", args);
}
-```
+````
-#### Single-file packages
+### Single-file packages
In addition to today's multi-file packages (`Cargo.toml` file with other `.rs`
files), we are adding the concept of single-file packages which may contain an
@@ -1541,22 +1224,8 @@ Single-file packages may be selected via `--manifest-path`, like
`cargo test --manifest-path foo.rs`. Unlike `Cargo.toml`, these files cannot be auto-discovered.
A single-file package may contain an embedded manifest. An embedded manifest
-is stored using `TOML` in a markdown code-fence with `cargo` at the start of the
-infostring inside a target-level doc-comment. It is an error to have multiple
-`cargo` code fences in the target-level doc-comment. We can relax this later,
-either merging the code fences or ignoring later code fences.
-
-Supported forms of embedded manifest are:
-``````rust
-//! ```cargo
-//! ```
-``````
-``````rust
-/*!
- * ```cargo
- * ```
- */
-``````
+is stored using `TOML` in rust "frontmatter", a markdown code-fence with `cargo`
+at the start of the infostring at the top of the file.
Inferred / defaulted manifest fields:
- `package.name = <slugified file stem>`
@@ -1580,7 +1249,7 @@ The lockfile for single-file packages will be placed in `CARGO_TARGET_DIR`. In
the future, when workspaces are supported, that will allow a user to have a
persistent lockfile.
-#### Manifest-commands
+### Manifest-commands
You may pass a manifest directly to the `cargo` command, without a subcommand,
like `foo/Cargo.toml` or a single-file package like `foo.rs`. This is mostly
@@ -1600,133 +1269,41 @@ Differences between `cargo run --manifest-path <path>` and `cargo <path>`
- `cargo <path>` runs with the config for `<path>` and not the current dir, more like `cargo install --path <path>`
- `cargo <path>` is at a verbosity level below the normal default. Pass `-v` to get normal output.
-### `[lints]`
-
-* Tracking Issue: [#12115](https://github.com/rust-lang/cargo/issues/12115)
-
-A new `lints` table would be added to configure lints:
-```toml
-[lints.rust]
-unsafe = "forbid"
-```
-and `cargo` would pass these along as flags to `rustc`, `clippy`, or other lint tools when `-Zlints` is used.
-
-This would work with
-[RFC 2906 `workspace-deduplicate`](https://rust-lang.github.io/rfcs/2906-cargo-workspace-deduplicate.html):
-```toml
-[lints]
-workspace = true
-
-[workspace.lints.rust]
-unsafe = "forbid"
-```
-
-#### Documentation Updates
-
-##### The `lints` section
+### Documentation Updates
-*as a new ["Manifest Format" entry](./manifest.html#the-manifest-format)*
-
-Override the default level of lints from different tools by assigning them to a new level in a
-table, for example:
-```toml
-[lints.rust]
-unsafe = "forbid"
-```
-
-This is short-hand for:
-```toml
-[lints.rust]
-unsafe = { level = "forbid", priority = 0 }
-```
+# Stabilized and removed features
-`level` corresponds to the lint levels in `rustc`:
-- `forbid`
-- `deny`
-- `warn`
-- `allow`
-
-`priority` is a signed integer that controls which lints or lint groups override other lint groups:
-- lower (particularly negative) numbers have lower priority, being overridden
- by higher numbers, and show up first on the command-line to tools like
- `rustc`
-
-To know which table under `[lints]` a particular lint belongs under, it is the part before `::` in the lint
-name. If there isn't a `::`, then the tool is `rust`. For example a warning
-about `unsafe` would be `lints.rust.unsafe` but a lint about
-`clippy::enum_glob_use` would be `lints.clippy.enum_glob_use`.
-
-For example:
-```toml
-[lints.rust]
-unsafe = "forbid"
-
-[lints.clippy]
-enum_glob_use = "deny"
-```
-
-##### The `lints` table
-
-*as a new [`[workspace]` entry](./workspaces.html#the-workspace-section)*
-
-The `workspace.lints` table is where you define lint configuration to be inherited by members of a workspace.
-
-Specifying a workspace lint configuration is similar to package lints.
-
-Example:
-
-```toml
-# [PROJECT_DIR]/Cargo.toml
-[workspace]
-members = ["crates/*"]
-
-[workspace.lints.rust]
-unsafe = "forbid"
-```
-
-```toml
-# [PROJECT_DIR]/crates/bar/Cargo.toml
-[package]
-name = "bar"
-version = "0.1.0"
-
-[lints]
-workspace = true
-```
-
-## Stabilized and removed features
-
-### Compile progress
+## Compile progress
The compile-progress feature has been stabilized in the 1.30 release.
Progress bars are now enabled by default.
See [`term.progress`](config.md#termprogresswhen) for more information about
controlling this feature.
-### Edition
+## Edition
Specifying the `edition` in `Cargo.toml` has been stabilized in the 1.31 release.
See [the edition field](manifest.md#the-edition-field) for more information
about specifying this field.
-### rename-dependency
+## rename-dependency
Specifying renamed dependencies in `Cargo.toml` has been stabilized in the 1.31 release.
See [renaming dependencies](specifying-dependencies.md#renaming-dependencies-in-cargotoml)
for more information about renaming dependencies.
-### Alternate Registries
+## Alternate Registries
Support for alternate registries has been stabilized in the 1.34 release.
See the [Registries chapter](registries.md) for more information about alternate registries.
-### Offline Mode
+## Offline Mode
The offline feature has been stabilized in the 1.36 release.
See the [`--offline` flag](../commands/cargo.md#option-cargo---offline) for
more information on using the offline mode.
-### publish-lockfile
+## publish-lockfile
The `publish-lockfile` feature has been removed in the 1.37 release.
The `Cargo.lock` file is always included when a package is published if the
@@ -1735,19 +1312,19 @@ to use the `Cargo.lock` file.
See [`cargo package`](../commands/cargo-package.md) and
[`cargo install`](../commands/cargo-install.md) for more information.
-### default-run
+## default-run
The `default-run` feature has been stabilized in the 1.37 release.
See [the `default-run` field](manifest.md#the-default-run-field) for more
information about specifying the default target to run.
-### cache-messages
+## cache-messages
Compiler message caching has been stabilized in the 1.40 release.
Compiler warnings are now cached by default and will be replayed automatically
when re-running Cargo.
-### install-upgrade
+## install-upgrade
The `install-upgrade` feature has been stabilized in the 1.41 release.
[`cargo install`] will now automatically upgrade packages if they appear to be
@@ -1755,129 +1332,129 @@ out-of-date. See the [`cargo install`] documentation for more information.
[`cargo install`]: ../commands/cargo-install.md
-### Profile Overrides
+## Profile Overrides
Profile overrides have been stabilized in the 1.41 release.
See [Profile Overrides](profiles.md#overrides) for more information on using
overrides.
-### Config Profiles
+## Config Profiles
Specifying profiles in Cargo config files and environment variables has been
stabilized in the 1.43 release.
See the [config `[profile]` table](config.md#profile) for more information
about specifying [profiles](profiles.md) in config files.
-### crate-versions
+## crate-versions
The `-Z crate-versions` flag has been stabilized in the 1.47 release.
The crate version is now automatically included in the
[`cargo doc`](../commands/cargo-doc.md) documentation sidebar.
-### Features
+## Features
The `-Z features` flag has been stabilized in the 1.51 release.
See [feature resolver version 2](features.md#feature-resolver-version-2)
for more information on using the new feature resolver.
-### package-features
+## package-features
The `-Z package-features` flag has been stabilized in the 1.51 release.
See the [resolver version 2 command-line flags](features.md#resolver-version-2-command-line-flags)
for more information on using the features CLI options.
-### Resolver
+## Resolver
The `resolver` feature in `Cargo.toml` has been stabilized in the 1.51 release.
See the [resolver versions](resolver.md#resolver-versions) for more
information about specifying resolvers.
-### extra-link-arg
+## extra-link-arg
The `extra-link-arg` feature to specify additional linker arguments in build
scripts has been stabilized in the 1.56 release. See the [build script
documentation](build-scripts.md#outputs-of-the-build-script) for more
information on specifying extra linker arguments.
-### configurable-env
+## configurable-env
The `configurable-env` feature to specify environment variables in Cargo
configuration has been stabilized in the 1.56 release. See the [config
documentation](config.html#env) for more information about configuring
environment variables.
-### rust-version
+## rust-version
The `rust-version` field in `Cargo.toml` has been stabilized in the 1.56 release.
See the [rust-version field](manifest.html#the-rust-version-field) for more
information on using the `rust-version` field and the `--ignore-rust-version` option.
-### patch-in-config
+## patch-in-config
The `-Z patch-in-config` flag, and the corresponding support for
`[patch]` section in Cargo configuration files has been stabilized in
the 1.56 release. See the [patch field](config.html#patch) for more
information.
-### edition 2021
+## edition 2021
The 2021 edition has been stabilized in the 1.56 release.
See the [`edition` field](manifest.md#the-edition-field) for more information on setting the edition.
See [`cargo fix --edition`](../commands/cargo-fix.md) and [The Edition Guide](../../edition-guide/index.html) for more information on migrating existing projects.
-### Custom named profiles
+## Custom named profiles
Custom named profiles have been stabilized in the 1.57 release. See the
[profiles chapter](profiles.md#custom-profiles) for more information.
-### Profile `strip` option
+## Profile `strip` option
The profile `strip` option has been stabilized in the 1.59 release. See the
[profiles chapter](profiles.md#strip) for more information.
-### Future incompat report
+## Future incompat report
Support for generating a future-incompat report has been stabilized
in the 1.59 release. See the [future incompat report chapter](future-incompat-report.md)
for more information.
-### Namespaced features
+## Namespaced features
Namespaced features has been stabilized in the 1.60 release.
See the [Features chapter](features.md#optional-dependencies) for more information.
-### Weak dependency features
+## Weak dependency features
Weak dependency features has been stabilized in the 1.60 release.
See the [Features chapter](features.md#dependency-features) for more information.
-### timings
+## timings
The `-Ztimings` option has been stabilized as `--timings` in the 1.60 release.
(`--timings=html` and the machine-readable `--timings=json` output remain
unstable and require `-Zunstable-options`.)
-### config-cli
+## config-cli
The `--config` CLI option has been stabilized in the 1.63 release. See
the [config documentation](config.html#command-line-overrides) for more
information.
-### multitarget
+## multitarget
The `-Z multitarget` option has been stabilized in the 1.64 release.
See [`build.target`](config.md#buildtarget) for more information about
setting the default [target platform triples][target triple].
-### crate-type
+## crate-type
The `--crate-type` flag for `cargo rustc` has been stabilized in the 1.64
release. See the [`cargo rustc` documentation](../commands/cargo-rustc.md)
for more information.
-### Workspace Inheritance
+## Workspace Inheritance
Workspace Inheritance has been stabilized in the 1.64 release.
See [workspace.package](workspaces.md#the-package-table),
@@ -1885,27 +1462,50 @@ See [workspace.package](workspaces.md#the-package-table),
and [inheriting-a-dependency-from-a-workspace](specifying-dependencies.md#inheriting-a-dependency-from-a-workspace)
for more information.
-### terminal-width
+## terminal-width
The `-Z terminal-width` option has been stabilized in the 1.68 release.
The terminal width is always passed to the compiler when running from a
terminal where Cargo can automatically detect the width.
-### sparse-registry
+## sparse-registry
Sparse registry support has been stabilized in the 1.68 release.
See [Registry Protocols](registries.md#registry-protocols) for more information.
-#### `cargo logout`
+### `cargo logout`
The [`cargo logout`] command has been stabilized in the 1.70 release.
[target triple]: ../appendix/glossary.md#target '"target" (glossary)'
+[`cargo logout`]: ../commands/cargo-logout.md
-
-### `doctest-in-workspace`
+## `doctest-in-workspace`
The `-Z doctest-in-workspace` option for `cargo test` has been stabilized and
enabled by default in the 1.72 release. See the
[`cargo test` documentation](../commands/cargo-test.md#working-directory-of-tests)
for more information about the working directory for compiling and running tests.
+
+## keep-going
+
+The `--keep-going` option has been stabilized in the 1.74 release. See the
+[`--keep-going` flag](../commands/cargo-build.html#option-cargo-build---keep-going)
+in `cargo build` as an example for more details.
+
+## `[lints]`
+
+[`[lints]`](manifest.html#the-lints-section) (enabled via `-Zlints`) has been stabilized in the 1.74 release.
+
+## credential-process
+
+The `-Z credential-process` feature has been stabilized in the 1.74 release.
+
+See [Registry Authentication](registry-authentication.md) documentation for details.
+
+## registry-auth
+
+The `-Z registry-auth` feature has been stabilized in the 1.74 release with the additional
+requirement that a credential-provider is configured.
+
+See [Registry Authentication](registry-authentication.md) documentation for details.
diff --git a/src/tools/cargo/src/doc/src/reference/workspaces.md b/src/tools/cargo/src/doc/src/reference/workspaces.md
index 36a2e7323..17637d6c7 100644
--- a/src/tools/cargo/src/doc/src/reference/workspaces.md
+++ b/src/tools/cargo/src/doc/src/reference/workspaces.md
@@ -1,4 +1,4 @@
-## Workspaces
+# Workspaces
A *workspace* is a collection of one or more packages, called *workspace
members*, that are managed together.
@@ -24,12 +24,13 @@ In the `Cargo.toml`, the `[workspace]` table supports the following sections:
* [`default-members`](#the-default-members-field) --- Packages to operate on when a specific package wasn't selected.
* [`package`](#the-package-table) --- Keys for inheriting in packages.
* [`dependencies`](#the-dependencies-table) --- Keys for inheriting in package dependencies.
+ * [`lints`](#the-lints-table) --- Keys for inheriting in package lints.
* [`metadata`](#the-metadata-table) --- Extra settings for external tools.
* [`[patch]`](overriding-dependencies.md#the-patch-section) --- Override dependencies.
* [`[replace]`](overriding-dependencies.md#the-replace-section) --- Override dependencies (deprecated).
* [`[profile]`](profiles.md) --- Compiler settings and optimizations.
-### The `[workspace]` section
+## The `[workspace]` section
To create a workspace, you add the `[workspace]` table to a `Cargo.toml`:
```toml
@@ -40,7 +41,7 @@ To create a workspace, you add the `[workspace]` table to a `Cargo.toml`:
At minimum, a workspace has to have a member, either with a root package or as
a virtual manifest.
-#### Root package
+### Root package
If the [`[workspace]` section](#the-workspace-section) is added to a
`Cargo.toml` that already defines a `[package]`, the package is
@@ -56,7 +57,7 @@ version = "0.1.0" # the current version, obeying semver
authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
```
-#### Virtual workspace
+### Virtual workspace
Alternatively, a `Cargo.toml` file can be created with a `[workspace]` section
but without a [`[package]` section][package]. This is called a *virtual
@@ -84,7 +85,7 @@ should be specified manually. It is usually deduced from the [`package.edition`]
field which is absent in virtual manifests and the edition field of a member
won't affect the resolver used by the workspace.
-### The `members` and `exclude` fields
+## The `members` and `exclude` fields
The `members` and `exclude` fields define which packages are members of
the workspace:
@@ -114,7 +115,7 @@ manifest key can be used in member crates to point at a workspace's root to
override this automatic search. The manual setting can be useful if the member
is not inside a subdirectory of the workspace root.
-#### Package selection
+### Package selection
In a workspace, package-related Cargo commands like [`cargo build`] can use
the `-p` / `--package` or `--workspace` command-line flags to determine which
@@ -124,7 +125,7 @@ a [virtual workspace](#virtual-workspace), it will apply to all members (as if
`--workspace` were specified on the command-line). See also
[`default-members`](#the-default-members-field).
-### The `default-members` field
+## The `default-members` field
The optional `default-members` key can be specified to set the members to
operate on when in the workspace root and the package selection flags are not
@@ -138,7 +139,7 @@ default-members = ["path/to/member2", "path/to/member3/foo"]
When specified, `default-members` must expand to a subset of `members`.
-### The `package` table
+## The `package` table
The `workspace.package` table is where you define keys that can be
inherited by members of a workspace. These keys can be inherited by
@@ -183,7 +184,7 @@ description.workspace = true
documentation.workspace = true
```
-### The `dependencies` table
+## The `dependencies` table
The `workspace.dependencies` table is where you define dependencies to be
inherited by members of a workspace.
@@ -222,7 +223,34 @@ cc.workspace = true
rand.workspace = true
```
-### The `metadata` table
+## The `lints` table
+
+The `workspace.lints` table is where you define lint configuration to be inherited by members of a workspace.
+
+Specifying a workspace lint configuration is similar to package lints.
+
+Example:
+
+```toml
+# [PROJECT_DIR]/Cargo.toml
+[workspace]
+members = ["crates/*"]
+
+[workspace.lints.rust]
+unsafe_code = "forbid"
+```
+
+```toml
+# [PROJECT_DIR]/crates/bar/Cargo.toml
+[package]
+name = "bar"
+version = "0.1.0"
+
+[lints]
+workspace = true
+```
+
+## The `metadata` table
The `workspace.metadata` table is ignored by Cargo and will not be warned
about. This section can be used for tools that would like to store workspace
diff --git a/src/tools/cargo/src/etc/_cargo b/src/tools/cargo/src/etc/_cargo
index 164d7679f..7fb335252 100644
--- a/src/tools/cargo/src/etc/_cargo
+++ b/src/tools/cargo/src/etc/_cargo
@@ -342,9 +342,11 @@ _cargo() {
update)
_arguments -s -S $common $manifest \
'--aggressive=[force dependency update]' \
+ '--recursive=[force dependency update]' \
"--dry-run[don't actually write the lockfile]" \
'(-p --package)'{-p+,--package=}'[specify package to update]:package:_cargo_package_names' \
- '--precise=[update single dependency to precise release]:release'
+ '--precise=[update single dependency to precise release]:release' \
+ '*:package:_cargo_package_names'
;;
verify-project)
@@ -406,9 +408,15 @@ _cargo_cmds() {
}
_cargo_target_triple() {
- local -a targets
- targets=( ${(f)"$(rustc --print target-list)"} )
- _describe 'target triple' targets
+ local -a result
+
+ if (( $+commands[rustup] )); then
+ result=( ${(f)"$(rustup target list --installed)"} )
+ else
+ result=( ${(f)"$(rustc --print target-list)"} )
+ fi
+
+ _describe 'target triple' result
}
#FIXME: Disabled until fixed
diff --git a/src/tools/cargo/src/etc/cargo.bashcomp.sh b/src/tools/cargo/src/etc/cargo.bashcomp.sh
index 33f225ebf..a1e800bc3 100644
--- a/src/tools/cargo/src/etc/cargo.bashcomp.sh
+++ b/src/tools/cargo/src/etc/cargo.bashcomp.sh
@@ -87,7 +87,7 @@ _cargo()
local opt__t="$opt__test"
local opt__tree="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock --target -i --invert --prefix --no-dedupe --duplicates -d --charset -f --format -e --edges"
local opt__uninstall="$opt_common $opt_lock $opt_pkg --bin --root"
- local opt__update="$opt_common $opt_mani $opt_lock $opt_pkg --aggressive --precise --dry-run"
+ local opt__update="$opt_common $opt_mani $opt_lock $opt_pkg --aggressive --recursive --precise --dry-run"
local opt__vendor="$opt_common $opt_mani $opt_lock $opt_sync --no-delete --respect-source-config --versioned-dirs"
local opt__verify_project="$opt_common $opt_mani $opt_lock"
local opt__version="$opt_common $opt_lock"
@@ -250,15 +250,11 @@ _get_examples(){
}
_get_targets(){
- local result=()
- local targets=$(rustup target list)
- while read line
- do
- if [[ "$line" =~ default|installed ]]; then
- result+=("${line%% *}")
- fi
- done <<< "$targets"
- echo "${result[@]}"
+ if command -v rustup >/dev/null 2>/dev/null; then
+ rustup target list --installed
+ else
+ rustc --print target-list
+ fi
}
_toolchains(){
diff --git a/src/tools/cargo/src/etc/man/cargo-bench.1 b/src/tools/cargo/src/etc/man/cargo-bench.1
index 993dd3415..64498c4d6 100644
--- a/src/tools/cargo/src/etc/man/cargo-bench.1
+++ b/src/tools/cargo/src/etc/man/cargo-bench.1
@@ -502,11 +502,16 @@ a string \fBdefault\fR is provided, it sets the value back to defaults.
Should not be 0.
.RE
.sp
-\fB\-\-keep\-going\fR
+While \fBcargo bench\fR involves compilation, it does not provide a \fB\-\-keep\-going\fR
+flag. Use \fB\-\-no\-fail\-fast\fR to run as many benchmarks as possible without
+stopping at the first failure. To \[lq]compile\[rq] as many benchmarks as possible, use
+\fB\-\-benches\fR to build benchmark binaries separately. For example:
+.sp
.RS 4
-Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-\fB\-Zunstable\-options\fR\&.
+.nf
+cargo build \-\-benches \-\-release \-\-keep\-going
+cargo bench \-\-no\-fail\-fast
+.fi
.RE
.SH "ENVIRONMENT"
See \fIthe reference\fR <https://doc.rust\-lang.org/cargo/reference/environment\-variables.html> for
diff --git a/src/tools/cargo/src/etc/man/cargo-build.1 b/src/tools/cargo/src/etc/man/cargo-build.1
index 4ee6a0d76..6bcfe8093 100644
--- a/src/tools/cargo/src/etc/man/cargo-build.1
+++ b/src/tools/cargo/src/etc/man/cargo-build.1
@@ -420,8 +420,13 @@ Should not be 0.
\fB\-\-keep\-going\fR
.RS 4
Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-\fB\-Zunstable\-options\fR\&.
+the build on the first one that fails to build.
+.sp
+For example if the current package depends on dependencies \fBfails\fR and \fBworks\fR,
+one of which fails to build, \fBcargo build \-j1\fR may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas \fBcargo build \-j1 \-\-keep\-going\fR would definitely run both
+builds, even if the one run first fails.
.RE
.sp
\fB\-\-future\-incompat\-report\fR
diff --git a/src/tools/cargo/src/etc/man/cargo-check.1 b/src/tools/cargo/src/etc/man/cargo-check.1
index 1aada2a21..fdbb84647 100644
--- a/src/tools/cargo/src/etc/man/cargo-check.1
+++ b/src/tools/cargo/src/etc/man/cargo-check.1
@@ -401,8 +401,13 @@ Should not be 0.
\fB\-\-keep\-going\fR
.RS 4
Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-\fB\-Zunstable\-options\fR\&.
+the build on the first one that fails to build.
+.sp
+For example if the current package depends on dependencies \fBfails\fR and \fBworks\fR,
+one of which fails to build, \fBcargo check \-j1\fR may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas \fBcargo check \-j1 \-\-keep\-going\fR would definitely run both
+builds, even if the one run first fails.
.RE
.sp
\fB\-\-future\-incompat\-report\fR
diff --git a/src/tools/cargo/src/etc/man/cargo-clean.1 b/src/tools/cargo/src/etc/man/cargo-clean.1
index 3cb321f05..d71b0e027 100644
--- a/src/tools/cargo/src/etc/man/cargo-clean.1
+++ b/src/tools/cargo/src/etc/man/cargo-clean.1
@@ -25,6 +25,12 @@ multiple times. See \fBcargo\-pkgid\fR(1) for the SPEC format.
.RE
.SS "Clean Options"
.sp
+\fB\-\-dry\-run\fR
+.RS 4
+Displays a summary of what would be deleted without deleting anything.
+Use with \fB\-\-verbose\fR to display the actual files that would be deleted.
+.RE
+.sp
\fB\-\-doc\fR
.RS 4
This option will cause \fBcargo clean\fR to remove only the \fBdoc\fR directory in
diff --git a/src/tools/cargo/src/etc/man/cargo-doc.1 b/src/tools/cargo/src/etc/man/cargo-doc.1
index 24621e9f6..2bdd8867b 100644
--- a/src/tools/cargo/src/etc/man/cargo-doc.1
+++ b/src/tools/cargo/src/etc/man/cargo-doc.1
@@ -368,8 +368,13 @@ Should not be 0.
\fB\-\-keep\-going\fR
.RS 4
Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-\fB\-Zunstable\-options\fR\&.
+the build on the first one that fails to build.
+.sp
+For example if the current package depends on dependencies \fBfails\fR and \fBworks\fR,
+one of which fails to build, \fBcargo doc \-j1\fR may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas \fBcargo doc \-j1 \-\-keep\-going\fR would definitely run both
+builds, even if the one run first fails.
.RE
.SH "ENVIRONMENT"
See \fIthe reference\fR <https://doc.rust\-lang.org/cargo/reference/environment\-variables.html> for
diff --git a/src/tools/cargo/src/etc/man/cargo-fix.1 b/src/tools/cargo/src/etc/man/cargo-fix.1
index 7f2a34cda..61083f214 100644
--- a/src/tools/cargo/src/etc/man/cargo-fix.1
+++ b/src/tools/cargo/src/etc/man/cargo-fix.1
@@ -496,8 +496,13 @@ Should not be 0.
\fB\-\-keep\-going\fR
.RS 4
Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-\fB\-Zunstable\-options\fR\&.
+the build on the first one that fails to build.
+.sp
+For example if the current package depends on dependencies \fBfails\fR and \fBworks\fR,
+one of which fails to build, \fBcargo fix \-j1\fR may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas \fBcargo fix \-j1 \-\-keep\-going\fR would definitely run both
+builds, even if the one run first fails.
.RE
.SH "ENVIRONMENT"
See \fIthe reference\fR <https://doc.rust\-lang.org/cargo/reference/environment\-variables.html> for
diff --git a/src/tools/cargo/src/etc/man/cargo-install.1 b/src/tools/cargo/src/etc/man/cargo-install.1
index 917c0d0e1..5ca3180fd 100644
--- a/src/tools/cargo/src/etc/man/cargo-install.1
+++ b/src/tools/cargo/src/etc/man/cargo-install.1
@@ -346,8 +346,13 @@ Should not be 0.
\fB\-\-keep\-going\fR
.RS 4
Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-\fB\-Zunstable\-options\fR\&.
+the build on the first one that fails to build.
+.sp
+For example if the current package depends on dependencies \fBfails\fR and \fBworks\fR,
+one of which fails to build, \fBcargo install \-j1\fR may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas \fBcargo install \-j1 \-\-keep\-going\fR would definitely run both
+builds, even if the one run first fails.
.RE
.SS "Display Options"
.sp
diff --git a/src/tools/cargo/src/etc/man/cargo-login.1 b/src/tools/cargo/src/etc/man/cargo-login.1
index 1ae1cc626..92b3b3f3c 100644
--- a/src/tools/cargo/src/etc/man/cargo-login.1
+++ b/src/tools/cargo/src/etc/man/cargo-login.1
@@ -4,14 +4,21 @@
.ad l
.ss \n[.ss] 0
.SH "NAME"
-cargo\-login \[em] Save an API token from the registry locally
+cargo\-login \[em] Log in to a registry
.SH "SYNOPSIS"
-\fBcargo login\fR [\fIoptions\fR] [\fItoken\fR]
+\fBcargo login\fR [\fIoptions\fR] [\fItoken\fR] \[en] [\fIargs\fR]
.SH "DESCRIPTION"
-This command will save the API token to disk so that commands that require
-authentication, such as \fBcargo\-publish\fR(1), will be automatically
-authenticated. The token is saved in \fB$CARGO_HOME/credentials.toml\fR\&. \fBCARGO_HOME\fR
-defaults to \fB\&.cargo\fR in your home directory.
+This command will run a credential provider to save a token so that commands
+that require authentication, such as \fBcargo\-publish\fR(1), will be
+automatically authenticated.
+.sp
+For the default \fBcargo:token\fR credential provider, the token is saved
+in \fB$CARGO_HOME/credentials.toml\fR\&. \fBCARGO_HOME\fR defaults to \fB\&.cargo\fR
+in your home directory.
+.sp
+If a registry has a credential\-provider specified, it will be used. Otherwise,
+the providers from the config value \fBregistry.global\-credential\-providers\fR will
+be attempted, starting from the end of the list.
.sp
If the \fItoken\fR argument is not specified, it will be read from stdin.
.sp
@@ -123,7 +130,7 @@ details on environment variables that Cargo reads.
.SH "EXAMPLES"
.sp
.RS 4
-\h'-04' 1.\h'+01'Save the API token to disk:
+\h'-04' 1.\h'+01'Save the token for the default registry:
.sp
.RS 4
.nf
@@ -131,5 +138,15 @@ cargo login
.fi
.RE
.RE
+.sp
+.RS 4
+\h'-04' 2.\h'+01'Save the token for a specific registry:
+.sp
+.RS 4
+.nf
+cargo login \-\-registry my\-registry
+.fi
+.RE
+.RE
.SH "SEE ALSO"
\fBcargo\fR(1), \fBcargo\-logout\fR(1), \fBcargo\-publish\fR(1)
diff --git a/src/tools/cargo/src/etc/man/cargo-logout.1 b/src/tools/cargo/src/etc/man/cargo-logout.1
index 7333cc62c..8d73e12a4 100644
--- a/src/tools/cargo/src/etc/man/cargo-logout.1
+++ b/src/tools/cargo/src/etc/man/cargo-logout.1
@@ -8,9 +8,15 @@ cargo\-logout \[em] Remove an API token from the registry locally
.SH "SYNOPSIS"
\fBcargo logout\fR [\fIoptions\fR]
.SH "DESCRIPTION"
-This command will remove the API token from the local credential storage.
-Credentials are stored in \fB$CARGO_HOME/credentials.toml\fR where \fB$CARGO_HOME\fR
-defaults to \fB\&.cargo\fR in your home directory.
+This command will run a credential provider to remove a saved token.
+.sp
+For the default \fBcargo:token\fR credential provider, credentials are stored
+in \fB$CARGO_HOME/credentials.toml\fR where \fB$CARGO_HOME\fR defaults to \fB\&.cargo\fR
+in your home directory.
+.sp
+If a registry has a credential\-provider specified, it will be used. Otherwise,
+the providers from the config value \fBregistry.global\-credential\-providers\fR will
+be attempted, starting from the end of the list.
.sp
If \fB\-\-registry\fR is not specified, then the credentials for the default
registry will be removed (configured by
diff --git a/src/tools/cargo/src/etc/man/cargo-metadata.1 b/src/tools/cargo/src/etc/man/cargo-metadata.1
index 95597d413..c1195c232 100644
--- a/src/tools/cargo/src/etc/man/cargo-metadata.1
+++ b/src/tools/cargo/src/etc/man/cargo-metadata.1
@@ -22,7 +22,7 @@ for a Rust API for reading the metadata.
.SS "Compatibility"
Within the same output format version, the compatibility is maintained, except
some scenarios. The following is a non\-exhaustive list of changes that are not
-considersed as incompatibile:
+considersed as incompatible:
.sp
.RS 4
\h'-04'\(bu\h'+02'\fBAdding new fields\fR \[em] New fields will be added when needed. Reserving this
diff --git a/src/tools/cargo/src/etc/man/cargo-package.1 b/src/tools/cargo/src/etc/man/cargo-package.1
index 8a7b1c191..f845cbc04 100644
--- a/src/tools/cargo/src/etc/man/cargo-package.1
+++ b/src/tools/cargo/src/etc/man/cargo-package.1
@@ -242,8 +242,13 @@ Should not be 0.
\fB\-\-keep\-going\fR
.RS 4
Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-\fB\-Zunstable\-options\fR\&.
+the build on the first one that fails to build.
+.sp
+For example if the current package depends on dependencies \fBfails\fR and \fBworks\fR,
+one of which fails to build, \fBcargo package \-j1\fR may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas \fBcargo package \-j1 \-\-keep\-going\fR would definitely run both
+builds, even if the one run first fails.
.RE
.SS "Display Options"
.sp
diff --git a/src/tools/cargo/src/etc/man/cargo-publish.1 b/src/tools/cargo/src/etc/man/cargo-publish.1
index d18f9e690..b2d95b9fd 100644
--- a/src/tools/cargo/src/etc/man/cargo-publish.1
+++ b/src/tools/cargo/src/etc/man/cargo-publish.1
@@ -27,8 +27,14 @@ which registries you are allowed to publish to.
.RE
.sp
.RS 4
-\h'-04' 3.\h'+01'Upload the crate to the registry. Note that the server will perform
-additional checks on the crate.
+\h'-04' 3.\h'+01'Upload the crate to the registry. The server will perform additional
+checks on the crate.
+.RE
+.sp
+.RS 4
+\h'-04' 4.\h'+01'The client will poll waiting for the package to appear in the index,
+and may timeout. In that case, you will need to check for completion
+manually. This timeout does not affect the upload.
.RE
.sp
This command requires you to be authenticated with either the \fB\-\-token\fR option
@@ -192,8 +198,13 @@ Should not be 0.
\fB\-\-keep\-going\fR
.RS 4
Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-\fB\-Zunstable\-options\fR\&.
+the build on the first one that fails to build.
+.sp
+For example if the current package depends on dependencies \fBfails\fR and \fBworks\fR,
+one of which fails to build, \fBcargo publish \-j1\fR may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas \fBcargo publish \-j1 \-\-keep\-going\fR would definitely run both
+builds, even if the one run first fails.
.RE
.SS "Display Options"
.sp
diff --git a/src/tools/cargo/src/etc/man/cargo-run.1 b/src/tools/cargo/src/etc/man/cargo-run.1
index 1c182ad1a..293814674 100644
--- a/src/tools/cargo/src/etc/man/cargo-run.1
+++ b/src/tools/cargo/src/etc/man/cargo-run.1
@@ -305,8 +305,13 @@ Should not be 0.
\fB\-\-keep\-going\fR
.RS 4
Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-\fB\-Zunstable\-options\fR\&.
+the build on the first one that fails to build.
+.sp
+For example if the current package depends on dependencies \fBfails\fR and \fBworks\fR,
+one of which fails to build, \fBcargo run \-j1\fR may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas \fBcargo run \-j1 \-\-keep\-going\fR would definitely run both
+builds, even if the one run first fails.
.RE
.SH "ENVIRONMENT"
See \fIthe reference\fR <https://doc.rust\-lang.org/cargo/reference/environment\-variables.html> for
diff --git a/src/tools/cargo/src/etc/man/cargo-rustc.1 b/src/tools/cargo/src/etc/man/cargo-rustc.1
index 50df99656..501e9208e 100644
--- a/src/tools/cargo/src/etc/man/cargo-rustc.1
+++ b/src/tools/cargo/src/etc/man/cargo-rustc.1
@@ -419,8 +419,13 @@ Should not be 0.
\fB\-\-keep\-going\fR
.RS 4
Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-\fB\-Zunstable\-options\fR\&.
+the build on the first one that fails to build.
+.sp
+For example if the current package depends on dependencies \fBfails\fR and \fBworks\fR,
+one of which fails to build, \fBcargo rustc \-j1\fR may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas \fBcargo rustc \-j1 \-\-keep\-going\fR would definitely run both
+builds, even if the one run first fails.
.RE
.sp
\fB\-\-future\-incompat\-report\fR
diff --git a/src/tools/cargo/src/etc/man/cargo-rustdoc.1 b/src/tools/cargo/src/etc/man/cargo-rustdoc.1
index 1792c6e2f..0335d6e54 100644
--- a/src/tools/cargo/src/etc/man/cargo-rustdoc.1
+++ b/src/tools/cargo/src/etc/man/cargo-rustdoc.1
@@ -387,8 +387,13 @@ Should not be 0.
\fB\-\-keep\-going\fR
.RS 4
Build as many crates in the dependency graph as possible, rather than aborting
-the build on the first one that fails to build. Unstable, requires
-\fB\-Zunstable\-options\fR\&.
+the build on the first one that fails to build.
+.sp
+For example if the current package depends on dependencies \fBfails\fR and \fBworks\fR,
+one of which fails to build, \fBcargo rustdoc \-j1\fR may or may not build the
+one that succeeds (depending on which one of the two builds Cargo picked to run
+first), whereas \fBcargo rustdoc \-j1 \-\-keep\-going\fR would definitely run both
+builds, even if the one run first fails.
.RE
.SH "ENVIRONMENT"
See \fIthe reference\fR <https://doc.rust\-lang.org/cargo/reference/environment\-variables.html> for
diff --git a/src/tools/cargo/src/etc/man/cargo-test.1 b/src/tools/cargo/src/etc/man/cargo-test.1
index 4ca150dbc..8e460e167 100644
--- a/src/tools/cargo/src/etc/man/cargo-test.1
+++ b/src/tools/cargo/src/etc/man/cargo-test.1
@@ -542,6 +542,18 @@ produced during execution of this command
.sp
See \fBcargo\-report\fR(1)
.RE
+.sp
+While \fBcargo test\fR involves compilation, it does not provide a \fB\-\-keep\-going\fR
+flag. Use \fB\-\-no\-fail\-fast\fR to run as many tests as possible without stopping at
+the first failure. To \[lq]compile\[rq] as many tests as possible, use \fB\-\-tests\fR to
+build test binaries separately. For example:
+.sp
+.RS 4
+.nf
+cargo build \-\-tests \-\-keep\-going
+cargo test \-\-tests \-\-no\-fail\-fast
+.fi
+.RE
.SH "ENVIRONMENT"
See \fIthe reference\fR <https://doc.rust\-lang.org/cargo/reference/environment\-variables.html> for
details on environment variables that Cargo reads.
diff --git a/src/tools/cargo/src/etc/man/cargo-update.1 b/src/tools/cargo/src/etc/man/cargo-update.1
index 6f697b3ab..c9fe881c8 100644
--- a/src/tools/cargo/src/etc/man/cargo-update.1
+++ b/src/tools/cargo/src/etc/man/cargo-update.1
@@ -6,7 +6,7 @@
.SH "NAME"
cargo\-update \[em] Update dependencies as recorded in the local lock file
.SH "SYNOPSIS"
-\fBcargo update\fR [\fIoptions\fR]
+\fBcargo update\fR [\fIoptions\fR] \fIspec\fR
.SH "DESCRIPTION"
This command will update dependencies in the \fBCargo.lock\fR file to the latest
version. If the \fBCargo.lock\fR file does not exist, it will be created with the
@@ -14,30 +14,29 @@ latest available versions.
.SH "OPTIONS"
.SS "Update Options"
.sp
-\fB\-p\fR \fIspec\fR\[u2026],
-\fB\-\-package\fR \fIspec\fR\[u2026]
+\fIspec\fR\[u2026]
.RS 4
Update only the specified packages. This flag may be specified
multiple times. See \fBcargo\-pkgid\fR(1) for the SPEC format.
.sp
-If packages are specified with the \fB\-p\fR flag, then a conservative update of
+If packages are specified with \fIspec\fR, then a conservative update of
the lockfile will be performed. This means that only the dependency specified
by SPEC will be updated. Its transitive dependencies will be updated only if
SPEC cannot be updated without updating dependencies. All other dependencies
will remain locked at their currently recorded versions.
.sp
-If \fB\-p\fR is not specified, all dependencies are updated.
+If \fIspec\fR is not specified, all dependencies are updated.
.RE
.sp
-\fB\-\-aggressive\fR
+\fB\-\-recursive\fR
.RS 4
-When used with \fB\-p\fR, dependencies of \fIspec\fR are forced to update as well.
+When used with \fIspec\fR, dependencies of \fIspec\fR are forced to update as well.
Cannot be used with \fB\-\-precise\fR\&.
.RE
.sp
\fB\-\-precise\fR \fIprecise\fR
.RS 4
-When used with \fB\-p\fR, allows you to specify a specific version number to set
+When used with \fIspec\fR, allows you to specify a specific version number to set
the package to. If the package comes from a git repository, this can be a git
revision (such as a SHA hash or tag).
.RE
@@ -200,7 +199,7 @@ cargo update
.sp
.RS 4
.nf
-cargo update \-p foo \-p bar
+cargo update foo bar
.fi
.RE
.RE
@@ -210,7 +209,7 @@ cargo update \-p foo \-p bar
.sp
.RS 4
.nf
-cargo update \-p foo \-\-precise 1.2.3
+cargo update foo \-\-precise 1.2.3
.fi
.RE
.RE
diff --git a/src/tools/cargo/tests/testsuite/alt_registry.rs b/src/tools/cargo/tests/testsuite/alt_registry.rs
index 91157cd53..d6d7dd531 100644
--- a/src/tools/cargo/tests/testsuite/alt_registry.rs
+++ b/src/tools/cargo/tests/testsuite/alt_registry.rs
@@ -1389,10 +1389,9 @@ fn both_index_and_registry() {
p.cargo(cmd)
.arg("--registry=foo")
.arg("--index=foo")
- .with_status(101)
- .with_stderr(
- "[ERROR] both `--index` and `--registry` \
- should not be set at the same time",
+ .with_status(1)
+ .with_stderr_contains(
+ "error: the argument '--registry <REGISTRY>' cannot be used with '--index <INDEX>'",
)
.run();
}
diff --git a/src/tools/cargo/tests/testsuite/artifact_dep.rs b/src/tools/cargo/tests/testsuite/artifact_dep.rs
index 08e413bf5..64aa9d8af 100644
--- a/src/tools/cargo/tests/testsuite/artifact_dep.rs
+++ b/src/tools/cargo/tests/testsuite/artifact_dep.rs
@@ -1445,13 +1445,7 @@ foo v0.0.0 ([CWD])
)
.run();
}
-
-// TODO: Fix this potentially by reverting 887562bfeb8c540594d7d08e6e9a4ab7eb255865 which adds artifact information to the registry
-// followed by 0ff93733626f7cbecaf9dce9ab62b4ced0be088e which picks it up.
-// For reference, see comments by ehuss https://github.com/rust-lang/cargo/pull/9992#discussion_r801086315 and
-// joshtriplett https://github.com/rust-lang/cargo/pull/9992#issuecomment-1033394197 .
#[cargo_test]
-#[ignore = "broken, need artifact info in index"]
fn targets_are_picked_up_from_non_workspace_artifact_deps() {
if cross_compile::disabled() {
return;
@@ -1464,6 +1458,7 @@ fn targets_are_picked_up_from_non_workspace_artifact_deps() {
let mut dep = registry::Dependency::new("artifact", "1.0.0");
Package::new("uses-artifact", "1.0.0")
+ .schema_version(3)
.file(
"src/lib.rs",
r#"pub fn uses_artifact() { let _b = include_bytes!(env!("CARGO_BIN_FILE_ARTIFACT")); }"#,
@@ -1496,6 +1491,127 @@ fn targets_are_picked_up_from_non_workspace_artifact_deps() {
}
#[cargo_test]
+fn index_version_filtering() {
+ if cross_compile::disabled() {
+ return;
+ }
+ let target = cross_compile::alternate();
+
+ Package::new("artifact", "1.0.0")
+ .file("src/main.rs", r#"fn main() {}"#)
+ .file("src/lib.rs", r#"pub fn lib() {}"#)
+ .publish();
+
+ let mut dep = registry::Dependency::new("artifact", "1.0.0");
+
+ Package::new("bar", "1.0.0").publish();
+ Package::new("bar", "1.0.1")
+ .schema_version(3)
+ .add_dep(dep.artifact("bin", Some(target.to_string())))
+ .publish();
+
+ // Verify that without `-Zbindeps` that it does not use 1.0.1.
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("tree")
+ .with_stdout("foo v0.1.0 [..]\n└── bar v1.0.0")
+ .run();
+
+ // And with -Zbindeps it can use 1.0.1.
+ p.cargo("update -Zbindeps")
+ .masquerade_as_nightly_cargo(&["bindeps"])
+ .with_stderr(
+ "\
+[UPDATING] [..]
+[ADDING] artifact v1.0.0
+[UPDATING] bar v1.0.0 -> v1.0.1",
+ )
+ .run();
+
+ // And without -Zbindeps, now that 1.0.1 is in Cargo.lock, it should fail.
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+[UPDATING] [..]
+error: failed to select a version for the requirement `bar = \"^1.0\"` (locked to 1.0.1)
+candidate versions found which didn't match: 1.0.0
+location searched: [..]
+required by package `foo v0.1.0 [..]`
+perhaps a crate was updated and forgotten to be re-vendored?",
+ )
+ .run();
+}
+
+// FIXME: `download_accessible` should work properly for artifact dependencies
+#[cargo_test]
+#[ignore = "broken, needs download_accessible fix"]
+fn proc_macro_in_artifact_dep() {
+ // Forcing FeatureResolver to check a proc-macro for a dependency behind a
+ // target dependency.
+ if cross_compile::disabled() {
+ return;
+ }
+ Package::new("pm", "1.0.0")
+ .file("src/lib.rs", "")
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "pm"
+ version = "1.0.0"
+
+ [lib]
+ proc-macro = true
+
+ "#,
+ )
+ .publish();
+ let alternate = cross_compile::alternate();
+ Package::new("bin-uses-pm", "1.0.0")
+ .target_dep("pm", "1.0", alternate)
+ .file("src/main.rs", "fn main() {}")
+ .publish();
+ // Simulate a network error downloading the proc-macro.
+ std::fs::remove_file(cargo_test_support::paths::root().join("dl/pm/1.0.0/download")).unwrap();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ edition = "2021"
+
+ [dependencies]
+ bin-uses-pm = {{ version = "1.0", artifact = "bin", target = "{alternate}"}}
+ "#
+ ),
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check -Z bindeps")
+ .masquerade_as_nightly_cargo(&["bindeps"])
+ .with_stderr("")
+ .run();
+}
+
+#[cargo_test]
fn allow_dep_renames_with_multiple_versions() {
Package::new("bar", "1.0.0")
.file("src/main.rs", r#"fn main() {println!("1.0.0")}"#)
@@ -1926,15 +2042,23 @@ You may press ctrl-c [..]
"badges": {},
"categories": [],
"deps": [{
+ "artifact": ["bin"],
"default_features": true,
"features": [],
"kind": "normal",
+ "lib": true,
"name": "bar",
"optional": false,
"target": null,
"version_req": "^1.0"
},
{
+ "artifact": [
+ "bin:a",
+ "cdylib",
+ "staticlib"
+ ],
+ "bindep_target": "target",
"default_features": true,
"features": [],
"kind": "build",
@@ -2894,8 +3018,8 @@ fn check_transitive_artifact_dependency_with_different_target() {
p.cargo("check -Z bindeps")
.masquerade_as_nightly_cargo(&["bindeps"])
.with_stderr_contains(
- "error: could not find specification for target `custom-target`.\n \
- Dependency `baz v0.0.0 [..]` requires to build for target `custom-target`.",
+ "error: failed to determine target information for target `custom-target`.\n \
+ Artifact dependency `baz` in package `bar v0.0.0 [..]` requires building for `custom-target`",
)
.with_status(101)
.run();
diff --git a/src/tools/cargo/tests/testsuite/bad_config.rs b/src/tools/cargo/tests/testsuite/bad_config.rs
index 4434ea90d..82da880ea 100644
--- a/src/tools/cargo/tests/testsuite/bad_config.rs
+++ b/src/tools/cargo/tests/testsuite/bad_config.rs
@@ -172,9 +172,6 @@ Caused by:
could not parse TOML configuration in `[..]`
Caused by:
- could not parse input as TOML
-
-Caused by:
TOML parse error at line 1, column 2
|
1 | 4
@@ -199,8 +196,11 @@ fn bad_cargo_lock() {
[ERROR] failed to parse lock file at: [..]Cargo.lock
Caused by:
+ TOML parse error at line 1, column 1
+ |
+ 1 | [[package]]
+ | ^^^^^^^^^^^
missing field `name`
- in `package`
",
)
.run();
@@ -303,8 +303,11 @@ fn bad_source_in_cargo_lock() {
[ERROR] failed to parse lock file at: [..]
Caused by:
+ TOML parse error at line 12, column 26
+ |
+ 12 | source = \"You shall not parse\"
+ | ^^^^^^^^^^^^^^^^^^^^^
invalid source `You shall not parse`
- in `package.source`
",
)
.run();
@@ -449,9 +452,6 @@ fn malformed_override() {
[ERROR] failed to parse manifest at `[..]`
Caused by:
- could not parse input as TOML
-
-Caused by:
TOML parse error at line 8, column 27
|
8 | native = {
@@ -804,9 +804,6 @@ Caused by:
could not parse TOML configuration in `[..]`
Caused by:
- could not parse input as TOML
-
-Caused by:
TOML parse error at line 1, column 7
|
1 | [bar] baz = 2
@@ -1288,8 +1285,11 @@ fn bad_dependency() {
error: failed to parse manifest at `[..]`
Caused by:
+ TOML parse error at line 8, column 23
+ |
+ 8 | bar = 3
+ | ^
invalid type: integer `3`, expected a version string like [..]
- in `dependencies.bar`
",
)
.run();
@@ -1320,8 +1320,11 @@ fn bad_debuginfo() {
error: failed to parse manifest [..]
Caused by:
+ TOML parse error at line 8, column 25
+ |
+ 8 | debug = 'a'
+ | ^^^
invalid value: string \"a\", expected a boolean, 0, 1, 2, \"line-tables-only\", or \"line-directives-only\"
- in `profile.dev.debug`
",
)
.run();
@@ -1352,8 +1355,11 @@ fn bad_debuginfo2() {
error: failed to parse manifest at `[..]`
Caused by:
+ TOML parse error at line 8, column 25
+ |
+ 8 | debug = 3.6
+ | ^^^
invalid type: floating point `3.6`, expected a boolean, 0, 1, 2, \"line-tables-only\", or \"line-directives-only\"
- in `profile.dev.debug`
",
)
.run();
@@ -1382,8 +1388,11 @@ fn bad_opt_level() {
error: failed to parse manifest at `[..]`
Caused by:
- expected a boolean or a string
- in `package.build`
+ TOML parse error at line 6, column 25
+ |
+ 6 | build = 3
+ | ^
+ invalid type: integer `3`, expected a boolean or string
",
)
.run();
@@ -1412,6 +1421,117 @@ fn warn_semver_metadata() {
}
#[cargo_test]
+fn bad_http_ssl_version() {
+ // Invalid type in SslVersionConfig.
+ let p = project()
+ .file(
+ ".cargo/config.toml",
+ r#"
+ [http]
+ ssl-version = ["tlsv1.2", "tlsv1.3"]
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] error in [..]/config.toml: could not load config key `http.ssl-version`
+
+Caused by:
+ invalid type: sequence, expected a string or map
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn bad_http_ssl_version_range() {
+ // Invalid type in SslVersionConfigRange.
+ let p = project()
+ .file(
+ ".cargo/config.toml",
+ r#"
+ [http]
+ ssl-version.min = false
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] error in [..]/config.toml: could not load config key `http.ssl-version`
+
+Caused by:
+ error in [..]/config.toml: `http.ssl-version.min` expected a string, but found a boolean
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn bad_build_jobs() {
+ // Invalid type in JobsConfig.
+ let p = project()
+ .file(
+ ".cargo/config.toml",
+ r#"
+ [build]
+ jobs = { default = true }
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] error in [..]/config.toml: could not load config key `build.jobs`
+
+Caused by:
+ invalid type: map, expected an integer or string
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn bad_build_target() {
+ // Invalid type in BuildTargetConfig.
+ let p = project()
+ .file(
+ ".cargo/config.toml",
+ r#"
+ [build]
+ target.'cfg(unix)' = "x86_64"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] error in [..]/config.toml: could not load config key `build.target`
+
+Caused by:
+ error in [..]/config.toml: could not load config key `build.target`
+
+Caused by:
+ invalid type: map, expected a string or array
+",
+ )
+ .run();
+}
+
+#[cargo_test]
fn bad_target_cfg() {
// Invalid type in a StringList.
//
diff --git a/src/tools/cargo/tests/testsuite/bench.rs b/src/tools/cargo/tests/testsuite/bench.rs
index d773308c6..01017e857 100644
--- a/src/tools/cargo/tests/testsuite/bench.rs
+++ b/src/tools/cargo/tests/testsuite/bench.rs
@@ -1671,24 +1671,6 @@ fn json_artifact_includes_executable_for_benchmark() {
.run();
}
-#[cargo_test]
-fn cargo_bench_no_keep_going() {
- let p = project()
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", "")
- .build();
-
- p.cargo("bench --keep-going")
- .with_stderr(
- "\
-error: unexpected argument `--keep-going` found
-
- tip: to run as many benchmarks as possible without failing fast, use `--no-fail-fast`",
- )
- .with_status(101)
- .run();
-}
-
#[cargo_test(nightly, reason = "bench")]
fn cargo_bench_print_env_verbose() {
let p = project()
diff --git a/src/tools/cargo/tests/testsuite/build.rs b/src/tools/cargo/tests/testsuite/build.rs
index 8cb064a6f..1afa83918 100644
--- a/src/tools/cargo/tests/testsuite/build.rs
+++ b/src/tools/cargo/tests/testsuite/build.rs
@@ -136,6 +136,29 @@ fn incremental_config() {
}
#[cargo_test]
+fn cargo_compile_with_redundant_default_mode() {
+ let p = project()
+ .file("Cargo.toml", &basic_bin_manifest("foo"))
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .build();
+
+ p.cargo("build --debug")
+ .with_stderr(
+ "\
+error: unexpected argument '--debug' found
+
+ tip: `--debug` is the default for `cargo build`; instead `--release` is supported
+
+Usage: cargo[EXE] build [OPTIONS]
+
+For more information, try '--help'.
+",
+ )
+ .with_status(1)
+ .run();
+}
+
+#[cargo_test]
fn cargo_compile_with_workspace_excluded() {
let p = project().file("src/main.rs", "fn main() {}").build();
@@ -259,9 +282,6 @@ fn cargo_compile_with_invalid_manifest2() {
[ERROR] failed to parse manifest at `[..]`
Caused by:
- could not parse input as TOML
-
-Caused by:
TOML parse error at line 3, column 23
|
3 | foo = bar
@@ -284,9 +304,6 @@ fn cargo_compile_with_invalid_manifest3() {
[ERROR] failed to parse manifest at `[..]`
Caused by:
- could not parse input as TOML
-
-Caused by:
TOML parse error at line 1, column 5
|
1 | a = bar
@@ -346,8 +363,11 @@ fn cargo_compile_with_invalid_version() {
[ERROR] failed to parse manifest at `[..]`
Caused by:
+ TOML parse error at line 4, column 19
+ |
+ 4 | version = \"1.0\"
+ | ^^^^^
unexpected end of input while parsing minor version number
- in `package.version`
",
)
.run();
@@ -3036,9 +3056,6 @@ Caused by:
could not parse TOML configuration in `[..]`
Caused by:
- could not parse input as TOML
-
-Caused by:
TOML parse error at line 1, column 6
|
1 | this is not valid toml
diff --git a/src/tools/cargo/tests/testsuite/build_script.rs b/src/tools/cargo/tests/testsuite/build_script.rs
index 400d10547..0ccbb4e27 100644
--- a/src/tools/cargo/tests/testsuite/build_script.rs
+++ b/src/tools/cargo/tests/testsuite/build_script.rs
@@ -453,6 +453,43 @@ fn custom_build_env_var_rustc_linker() {
p.cargo("build --target").arg(&target).run();
}
+// Only run this test on linux, since it's difficult to construct
+// a case suitable for all platforms.
+// See:https://github.com/rust-lang/cargo/pull/12535#discussion_r1306618264
+#[cargo_test]
+#[cfg(target_os = "linux")]
+fn custom_build_env_var_rustc_linker_with_target_cfg() {
+ if cross_compile::disabled() {
+ return;
+ }
+
+ let target = cross_compile::alternate();
+ let p = project()
+ .file(
+ ".cargo/config",
+ r#"
+ [target.'cfg(target_pointer_width = "32")']
+ linker = "/path/to/linker"
+ "#,
+ )
+ .file(
+ "build.rs",
+ r#"
+ use std::env;
+
+ fn main() {
+ assert!(env::var("RUSTC_LINKER").unwrap().ends_with("/path/to/linker"));
+ }
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ // no crate type set => linker never called => build succeeds if and
+ // only if build.rs succeeds, despite linker binary not existing.
+ p.cargo("build --target").arg(&target).run();
+}
+
#[cargo_test]
fn custom_build_env_var_rustc_linker_bad_host_target() {
let target = rustc_host();
diff --git a/src/tools/cargo/tests/testsuite/cargo/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo/help/stdout.log
index 26bcd745b..e15848ab7 100644
--- a/src/tools/cargo/tests/testsuite/cargo/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo/help/stdout.log
@@ -6,7 +6,7 @@ Usage: cargo [..][OPTIONS] [COMMAND]
Options:
-V, --version Print version info and exit
--list List installed commands
- --explain <CODE> Run `rustc --explain CODE`
+ --explain <CODE> Provide a detailed explanation of a rustc error message
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
-q, --quiet Do not print cargo log messages
--color <WHEN> Coloring: auto, always, never
@@ -18,7 +18,7 @@ Options:
-Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
-h, --help Print help
-Some common cargo commands are (see all commands with --list):
+Commands:
build, b Compile the current package
check, c Analyze the current package and report errors, but don't build object files
clean Remove the target directory
@@ -35,5 +35,6 @@ Some common cargo commands are (see all commands with --list):
publish Package and upload this package to the registry
install Install a Rust binary. Default location is $HOME/.cargo/bin
uninstall Uninstall a Rust binary
+ ... See all commands with --list
See 'cargo help <command>' for more information on a specific command.
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/in/Cargo.toml
new file mode 100644
index 000000000..3ecdb6681
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/in/Cargo.toml
@@ -0,0 +1,5 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/README.md b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/in/src/lib.rs
index e69de29bb..e69de29bb 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/README.md
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/mod.rs
new file mode 100644
index 000000000..467e9a681
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/mod.rs
@@ -0,0 +1,38 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+use itertools::Itertools;
+
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ const MANY_FEATURES_COUNT: usize = 200;
+ const ACTIVATED_FEATURES_COUNT: usize = 100;
+
+ cargo_test_support::registry::init();
+ let mut test_package =
+ cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package");
+ for i in 0..MANY_FEATURES_COUNT {
+ test_package.feature(format!("eyes{i:03}").as_str(), &[]);
+ }
+ test_package.publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ let features = (0..ACTIVATED_FEATURES_COUNT)
+ .map(|i| format!("eyes{i:03}"))
+ .join(",");
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .arg_line(format!("your-face --features {features}").as_str())
+ .current_dir(cwd)
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/out/Cargo.toml
new file mode 100644
index 000000000..6c8c7e5a3
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/out/Cargo.toml
@@ -0,0 +1,8 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+your-face = { version = "99999.0.0", features = ["eyes000", "eyes001", "eyes002", "eyes003", "eyes004", "eyes005", "eyes006", "eyes007", "eyes008", "eyes009", "eyes010", "eyes011", "eyes012", "eyes013", "eyes014", "eyes015", "eyes016", "eyes017", "eyes018", "eyes019", "eyes020", "eyes021", "eyes022", "eyes023", "eyes024", "eyes025", "eyes026", "eyes027", "eyes028", "eyes029", "eyes030", "eyes031", "eyes032", "eyes033", "eyes034", "eyes035", "eyes036", "eyes037", "eyes038", "eyes039", "eyes040", "eyes041", "eyes042", "eyes043", "eyes044", "eyes045", "eyes046", "eyes047", "eyes048", "eyes049", "eyes050", "eyes051", "eyes052", "eyes053", "eyes054", "eyes055", "eyes056", "eyes057", "eyes058", "eyes059", "eyes060", "eyes061", "eyes062", "eyes063", "eyes064", "eyes065", "eyes066", "eyes067", "eyes068", "eyes069", "eyes070", "eyes071", "eyes072", "eyes073", "eyes074", "eyes075", "eyes076", "eyes077", "eyes078", "eyes079", "eyes080", "eyes081", "eyes082", "eyes083", "eyes084", "eyes085", "eyes086", "eyes087", "eyes088", "eyes089", "eyes090", "eyes091", "eyes092", "eyes093", "eyes094", "eyes095", "eyes096", "eyes097", "eyes098", "eyes099"] }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/stderr.log
new file mode 100644
index 000000000..9288319aa
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/stderr.log
@@ -0,0 +1,5 @@
+ Updating `dummy-registry` index
+ Adding your-face v99999.0.0 to dependencies.
+ Features:
+ 100 activated features
+ 100 deactivated features
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/stdout.log
index e69de29bb..e69de29bb 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_activated_over_limit/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/in/Cargo.toml
new file mode 100644
index 000000000..3ecdb6681
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/in/Cargo.toml
@@ -0,0 +1,5 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/mod.rs
new file mode 100644
index 000000000..b2ed6f87d
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/mod.rs
@@ -0,0 +1,38 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+use itertools::Itertools;
+
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ const MANY_FEATURES_COUNT: usize = 200;
+ const ACTIVATED_FEATURES_COUNT: usize = 30;
+
+ cargo_test_support::registry::init();
+ let mut test_package =
+ cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package");
+ for i in 0..MANY_FEATURES_COUNT {
+ test_package.feature(format!("eyes{i:03}").as_str(), &[]);
+ }
+ test_package.publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ let features = (0..ACTIVATED_FEATURES_COUNT)
+ .map(|i| format!("eyes{i:03}"))
+ .join(",");
+ snapbox::cmd::Command::cargo_ui()
+ .arg("add")
+ .arg_line(format!("your-face --features {features}").as_str())
+ .current_dir(cwd)
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/out/Cargo.toml
new file mode 100644
index 000000000..b94cde668
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/out/Cargo.toml
@@ -0,0 +1,8 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+
+[dependencies]
+your-face = { version = "99999.0.0", features = ["eyes000", "eyes001", "eyes002", "eyes003", "eyes004", "eyes005", "eyes006", "eyes007", "eyes008", "eyes009", "eyes010", "eyes011", "eyes012", "eyes013", "eyes014", "eyes015", "eyes016", "eyes017", "eyes018", "eyes019", "eyes020", "eyes021", "eyes022", "eyes023", "eyes024", "eyes025", "eyes026", "eyes027", "eyes028", "eyes029"] }
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/stderr.log
new file mode 100644
index 000000000..7f74e6bf0
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/stderr.log
@@ -0,0 +1,34 @@
+ Updating `dummy-registry` index
+ Adding your-face v99999.0.0 to dependencies.
+ Features:
+ + eyes000
+ + eyes001
+ + eyes002
+ + eyes003
+ + eyes004
+ + eyes005
+ + eyes006
+ + eyes007
+ + eyes008
+ + eyes009
+ + eyes010
+ + eyes011
+ + eyes012
+ + eyes013
+ + eyes014
+ + eyes015
+ + eyes016
+ + eyes017
+ + eyes018
+ + eyes019
+ + eyes020
+ + eyes021
+ + eyes022
+ + eyes023
+ + eyes024
+ + eyes025
+ + eyes026
+ + eyes027
+ + eyes028
+ + eyes029
+ 170 deactivated features
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_add/features_deactivated_over_limit/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_add/help/stdout.log
index 0daba1a94..cf2a91313 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/help/stdout.log
@@ -42,7 +42,7 @@ Options:
--ignore-rust-version
Ignore `rust-version` specification in packages (unstable)
- --dry-run
+ -n, --dry-run
Don't actually write the manifest
-q, --quiet
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/invalid_manifest/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/invalid_manifest/stderr.log
index 3dabde349..9a8a93b5e 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/invalid_manifest/stderr.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/invalid_manifest/stderr.log
@@ -1,9 +1,6 @@
error: failed to parse manifest at `[ROOT]/case/Cargo.toml`
Caused by:
- could not parse input as TOML
-
-Caused by:
TOML parse error at line 8, column 7
|
8 | key = invalid-value
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/mod.rs
index de93afbc1..8c03b30dc 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_add/mod.rs
@@ -18,6 +18,8 @@ mod dev_prefer_existing_version;
mod dry_run;
mod empty_dep_table;
mod features;
+mod features_activated_over_limit;
+mod features_deactivated_over_limit;
mod features_empty;
mod features_multiple_occurrences;
mod features_preserve;
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs
index a382d95f1..f8aac0ad8 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/mod.rs
@@ -26,7 +26,7 @@ fn case() {
.current_dir(cwd)
.masquerade_as_nightly_cargo(&["msrv-policy"])
.assert()
- .success()
+ .code(101)
.stdout_matches_path(curr_dir!().join("stdout.log"))
.stderr_matches_path(curr_dir!().join("stderr.log"));
diff --git a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log
index 430abe31b..96bcbddc2 100644
--- a/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log
+++ b/src/tools/cargo/tests/testsuite/cargo_add/rust_version_ignore/stderr.log
@@ -1,2 +1,7 @@
Updating `dummy-registry` index
Adding rust-version-user v0.2.1 to dependencies.
+error: failed to select a version for the requirement `rust-version-user = "^0.2.1"`
+candidate versions found which didn't match: 0.2.1, 0.1.0
+location searched: `dummy-registry` index (which is replacing registry `crates-io`)
+required by package `cargo-list-test-fixture v0.0.0 ([ROOT]/case)`
+perhaps a crate was updated and forgotten to be re-vendored?
diff --git a/src/tools/cargo/tests/testsuite/cargo_alias_config.rs b/src/tools/cargo/tests/testsuite/cargo_alias_config.rs
index fd4aec917..679ca3d5f 100644
--- a/src/tools/cargo/tests/testsuite/cargo_alias_config.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_alias_config.rs
@@ -53,9 +53,6 @@ Caused by:
could not parse TOML configuration in `[..]/config`
Caused by:
- [..]
-
-Caused by:
TOML parse error at line [..]
|
3 | b-cargo-test = `
diff --git a/src/tools/cargo/tests/testsuite/cargo_bench/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_bench/help/stdout.log
index 5d9484df9..430d8be42 100644
--- a/src/tools/cargo/tests/testsuite/cargo_bench/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_bench/help/stdout.log
@@ -45,7 +45,7 @@ Feature Selection:
Compilation Options:
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
--profile <PROFILE-NAME> Build artifacts with the specified profile
- --target <TRIPLE> Build for the target triple
+ --target [<TRIPLE>] Build for the target triple
--target-dir <DIRECTORY> Directory for all generated artifacts
--unit-graph Output build graph in JSON (unstable)
--timings[=<FMTS>] Timing output formats (unstable) (comma separated): html, json
diff --git a/src/tools/cargo/tests/testsuite/cargo_bench/mod.rs b/src/tools/cargo/tests/testsuite/cargo_bench/mod.rs
index c0ce11180..28be9d1a7 100644
--- a/src/tools/cargo/tests/testsuite/cargo_bench/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_bench/mod.rs
@@ -1 +1,2 @@
mod help;
+mod no_keep_going;
diff --git a/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/in/Cargo.toml
new file mode 100644
index 000000000..c35d63273
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/in/Cargo.toml
@@ -0,0 +1,3 @@
+[package]
+name = "foo"
+version = "0.1.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/mod.rs b/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/mod.rs
new file mode 100644
index 000000000..6ed5f81f9
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/mod.rs
@@ -0,0 +1,19 @@
+use cargo_test_support::curr_dir;
+use cargo_test_support::CargoCommand;
+use cargo_test_support::Project;
+
+#[cargo_test]
+fn case() {
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("bench")
+ .arg("--keep-going")
+ .current_dir(cwd)
+ .assert()
+ .code(1)
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/stderr.log b/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/stderr.log
new file mode 100644
index 000000000..7b94abbc4
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/stderr.log
@@ -0,0 +1,7 @@
+error: unexpected argument '--keep-going' found
+
+ tip: use `--no-fail-fast` to run as many tests as possible regardless of failure
+
+Usage: cargo[EXE] bench [OPTIONS] [BENCHNAME] [-- [args]...]
+
+For more information, try '--help'.
diff --git a/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/stdout.log b/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_bench/no_keep_going/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_build/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_build/help/stdout.log
index af906c24f..56b934cd1 100644
--- a/src/tools/cargo/tests/testsuite/cargo_build/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_build/help/stdout.log
@@ -41,8 +41,8 @@ Compilation Options:
-r, --release Build artifacts in release mode, with optimizations
--profile <PROFILE-NAME> Build artifacts with the specified profile
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
- --keep-going Do not abort the build as soon as there is an error (unstable)
- --target <TRIPLE> Build for the target triple
+ --keep-going Do not abort the build as soon as there is an error
+ --target [<TRIPLE>] Build for the target triple
--target-dir <DIRECTORY> Directory for all generated artifacts
--out-dir <PATH> Copy final artifacts to this directory (unstable)
--build-plan Output the build plan in JSON (unstable)
diff --git a/src/tools/cargo/tests/testsuite/cargo_check/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_check/help/stdout.log
index 7c87615cd..92d44a6de 100644
--- a/src/tools/cargo/tests/testsuite/cargo_check/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_check/help/stdout.log
@@ -39,10 +39,10 @@ Feature Selection:
Compilation Options:
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
- --keep-going Do not abort the build as soon as there is an error (unstable)
+ --keep-going Do not abort the build as soon as there is an error
-r, --release Check artifacts in release mode, with optimizations
--profile <PROFILE-NAME> Check artifacts with the specified profile
- --target <TRIPLE> Check for the target triple
+ --target [<TRIPLE>] Check for the target triple
--target-dir <DIRECTORY> Directory for all generated artifacts
--unit-graph Output build graph in JSON (unstable)
--timings[=<FMTS>] Timing output formats (unstable) (comma separated): html, json
diff --git a/src/tools/cargo/tests/testsuite/cargo_clean/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_clean/help/stdout.log
index fd3c8855c..6e9e82772 100644
--- a/src/tools/cargo/tests/testsuite/cargo_clean/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_clean/help/stdout.log
@@ -5,6 +5,7 @@ Usage: cargo[EXE] clean [OPTIONS]
Options:
--doc Whether or not to clean just the documentation directory
-q, --quiet Do not print cargo log messages
+ -n, --dry-run Display what would be deleted without deleting anything
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
--color <WHEN> Coloring: auto, always, never
--config <KEY=VALUE> Override a configuration value
@@ -17,7 +18,7 @@ Package Selection:
Compilation Options:
-r, --release Whether or not to clean release artifacts
--profile <PROFILE-NAME> Clean artifacts of the specified profile
- --target <TRIPLE> Target triple to clean output for
+ --target [<TRIPLE>] Target triple to clean output for
--target-dir <DIRECTORY> Directory for all generated artifacts
Manifest Options:
diff --git a/src/tools/cargo/tests/testsuite/cargo_config/mod.rs b/src/tools/cargo/tests/testsuite/cargo_config/mod.rs
index dc0a40ed8..c1769fb53 100644
--- a/src/tools/cargo/tests/testsuite/cargo_config/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_config/mod.rs
@@ -84,7 +84,7 @@ fn get_toml() {
alias.foo = \"abc --xyz\"
alias.sub-example = [\"sub\", \"example\"]
build.jobs = 99
-build.rustflags = [\"--flag-directory\", \"--flag-global\"]
+build.rustflags = [\"--flag-global\", \"--flag-directory\"]
extra-table.somekey = \"somevalue\"
profile.dev.opt-level = 3
profile.dev.package.foo.opt-level = 1
@@ -111,7 +111,7 @@ target.\"cfg(target_os = \\\"linux\\\")\".runner = \"runme\"
cargo_process("config get build.rustflags -Zunstable-options")
.cwd(&sub_folder.parent().unwrap())
.masquerade_as_nightly_cargo(&["cargo-config"])
- .with_stdout("build.rustflags = [\"--flag-directory\", \"--flag-global\"]")
+ .with_stdout("build.rustflags = [\"--flag-global\", \"--flag-directory\"]")
.with_stderr("")
.run();
@@ -171,8 +171,8 @@ fn get_json() {
"build": {
"jobs": 99,
"rustflags": [
- "--flag-directory",
- "--flag-global"
+ "--flag-global",
+ "--flag-directory"
]
},
"extra-table": {
@@ -259,8 +259,8 @@ alias.sub-example = [
]
build.jobs = 99 # [ROOT]/home/.cargo/config.toml
build.rustflags = [
- \"--flag-directory\", # [ROOT]/foo/.cargo/config.toml
\"--flag-global\", # [ROOT]/home/.cargo/config.toml
+ \"--flag-directory\", # [ROOT]/foo/.cargo/config.toml
]
extra-table.somekey = \"somevalue\" # [ROOT]/home/.cargo/config.toml
profile.dev.opt-level = 3 # [ROOT]/home/.cargo/config.toml
@@ -280,8 +280,8 @@ target.\"cfg(target_os = \\\"linux\\\")\".runner = \"runme\" # [ROOT]/home/.carg
.with_stdout(
"\
build.rustflags = [
- \"--flag-directory\", # [ROOT]/foo/.cargo/config.toml
\"--flag-global\", # [ROOT]/home/.cargo/config.toml
+ \"--flag-directory\", # [ROOT]/foo/.cargo/config.toml
\"env1\", # environment variable `CARGO_BUILD_RUSTFLAGS`
\"env2\", # environment variable `CARGO_BUILD_RUSTFLAGS`
]
@@ -310,12 +310,12 @@ fn show_origin_toml_cli() {
.with_stdout(
"\
build.rustflags = [
- \"--flag-directory\", # [ROOT]/foo/.cargo/config.toml
\"--flag-global\", # [ROOT]/home/.cargo/config.toml
- \"cli1\", # --config cli option
- \"cli2\", # --config cli option
+ \"--flag-directory\", # [ROOT]/foo/.cargo/config.toml
\"env1\", # environment variable `CARGO_BUILD_RUSTFLAGS`
\"env2\", # environment variable `CARGO_BUILD_RUSTFLAGS`
+ \"cli1\", # --config cli option
+ \"cli2\", # --config cli option
]
",
)
@@ -471,7 +471,7 @@ fn includes() {
cargo_process("config get build.rustflags -Zunstable-options -Zconfig-include")
.cwd(&sub_folder.parent().unwrap())
.masquerade_as_nightly_cargo(&["cargo-config", "config-include"])
- .with_stdout(r#"build.rustflags = ["--flag-other", "--flag-directory", "--flag-global"]"#)
+ .with_stdout(r#"build.rustflags = ["--flag-global", "--flag-other", "--flag-directory"]"#)
.with_stderr("")
.run();
@@ -481,9 +481,9 @@ fn includes() {
.with_stdout(
"\
build.rustflags = [
+ \"--flag-global\", # [ROOT]/home/.cargo/config.toml
\"--flag-other\", # [ROOT]/foo/.cargo/other.toml
\"--flag-directory\", # [ROOT]/foo/.cargo/config.toml
- \"--flag-global\", # [ROOT]/home/.cargo/config.toml
]
",
)
diff --git a/src/tools/cargo/tests/testsuite/cargo_doc/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_doc/help/stdout.log
index 480e189c1..8ff5f9b72 100644
--- a/src/tools/cargo/tests/testsuite/cargo_doc/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_doc/help/stdout.log
@@ -36,10 +36,10 @@ Target Selection:
Compilation Options:
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
- --keep-going Do not abort the build as soon as there is an error (unstable)
+ --keep-going Do not abort the build as soon as there is an error
-r, --release Build artifacts in release mode, with optimizations
--profile <PROFILE-NAME> Build artifacts with the specified profile
- --target <TRIPLE> Build for the target triple
+ --target [<TRIPLE>] Build for the target triple
--target-dir <DIRECTORY> Directory for all generated artifacts
--unit-graph Output build graph in JSON (unstable)
--timings[=<FMTS>] Timing output formats (unstable) (comma separated): html, json
diff --git a/src/tools/cargo/tests/testsuite/cargo_features.rs b/src/tools/cargo/tests/testsuite/cargo_features.rs
index ed5f53a1e..cf7ef0190 100644
--- a/src/tools/cargo/tests/testsuite/cargo_features.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_features.rs
@@ -676,8 +676,11 @@ fn wrong_position() {
error: failed to parse manifest at [..]
Caused by:
- cargo-features = [\"test-dummy-unstable\"] was found in the wrong location: it \
- should be set at the top of Cargo.toml before any tables
+ TOML parse error at line 5, column 34
+ |
+ 5 | cargo-features = [\"test-dummy-unstable\"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ the field `cargo-features` should be set at the top of Cargo.toml before any tables
",
)
.run();
diff --git a/src/tools/cargo/tests/testsuite/cargo_fetch/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_fetch/help/stdout.log
index b9bd6c35b..32f29f1b3 100644
--- a/src/tools/cargo/tests/testsuite/cargo_fetch/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_fetch/help/stdout.log
@@ -11,7 +11,7 @@ Options:
-h, --help Print help
Compilation Options:
- --target <TRIPLE> Fetch dependencies for the target triple
+ --target [<TRIPLE>] Fetch dependencies for the target triple
Manifest Options:
--manifest-path <PATH> Path to Cargo.toml
diff --git a/src/tools/cargo/tests/testsuite/cargo_fix/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_fix/help/stdout.log
index c0a98218a..dbbd11b77 100644
--- a/src/tools/cargo/tests/testsuite/cargo_fix/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_fix/help/stdout.log
@@ -44,10 +44,10 @@ Feature Selection:
Compilation Options:
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
- --keep-going Do not abort the build as soon as there is an error (unstable)
+ --keep-going Do not abort the build as soon as there is an error
-r, --release Fix artifacts in release mode, with optimizations
--profile <PROFILE-NAME> Build artifacts with the specified profile
- --target <TRIPLE> Fix for the target triple
+ --target [<TRIPLE>] Fix for the target triple
--target-dir <DIRECTORY> Directory for all generated artifacts
--timings[=<FMTS>] Timing output formats (unstable) (comma separated): html, json
diff --git a/src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/clean-glob b/src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/clean-glob
index a9d37c560..eb5a316cb 100644
--- a/src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/clean-glob
+++ b/src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/clean-glob
@@ -1,2 +1 @@
target
-Cargo.lock
diff --git a/src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/ignore-glob b/src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/ignore-glob
index a9d37c560..eb5a316cb 100644
--- a/src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/ignore-glob
+++ b/src/tools/cargo/tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/ignore-glob
@@ -1,2 +1 @@
target
-Cargo.lock
diff --git a/src/tools/cargo/tests/testsuite/cargo_init/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_init/help/stdout.log
index 5dfb02498..0eb4c976b 100644
--- a/src/tools/cargo/tests/testsuite/cargo_init/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_init/help/stdout.log
@@ -6,10 +6,9 @@ Arguments:
[path] [default: .]
Options:
- --vcs <VCS> Initialize a new repository for the given version control system (git,
- hg, pijul, or fossil) or do not initialize any version control at all
- (none), overriding a global configuration. [possible values: git, hg,
- pijul, fossil, none]
+ --vcs <VCS> Initialize a new repository for the given version control system,
+ overriding a global configuration. [possible values: git, hg, pijul,
+ fossil, none]
--bin Use a binary (application) template [default]
--lib Use a library template
--edition <YEAR> Edition to set for the crate generated [possible values: 2015, 2018,
diff --git a/src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/out/.ignore b/src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/out/.ignore
index 4fffb2f89..ea8c4bf7f 100644
--- a/src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/out/.ignore
+++ b/src/tools/cargo/tests/testsuite/cargo_init/pijul_autodetect/out/.ignore
@@ -1,2 +1 @@
/target
-/Cargo.lock
diff --git a/src/tools/cargo/tests/testsuite/cargo_install/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_install/help/stdout.log
index a07fa47f6..2267c5f6b 100644
--- a/src/tools/cargo/tests/testsuite/cargo_install/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_install/help/stdout.log
@@ -42,9 +42,9 @@ Feature Selection:
Compilation Options:
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
- --keep-going Do not abort the build as soon as there is an error (unstable)
+ --keep-going Do not abort the build as soon as there is an error
--profile <PROFILE-NAME> Install artifacts with the specified profile
- --target <TRIPLE> Build for the target triple
+ --target [<TRIPLE>] Build for the target triple
--target-dir <DIRECTORY> Directory for all generated artifacts
--timings[=<FMTS>] Timing output formats (unstable) (comma separated): html, json
diff --git a/src/tools/cargo/tests/testsuite/cargo_login/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_login/help/stdout.log
index faec55c18..fd0f3eb3d 100644
--- a/src/tools/cargo/tests/testsuite/cargo_login/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_login/help/stdout.log
@@ -4,7 +4,7 @@ Usage: cargo[EXE] login [OPTIONS] [token] [-- [args]...]
Arguments:
[token]
- [args]... Arguments for the credential provider (unstable)
+ [args]... Additional arguments for the credential provider
Options:
--registry <REGISTRY> Registry to use
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_new/help/stdout.log
index 7252e0da1..a937f619b 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_new/help/stdout.log
@@ -6,10 +6,9 @@ Arguments:
<path>
Options:
- --vcs <VCS> Initialize a new repository for the given version control system (git,
- hg, pijul, or fossil) or do not initialize any version control at all
- (none), overriding a global configuration. [possible values: git, hg,
- pijul, fossil, none]
+ --vcs <VCS> Initialize a new repository for the given version control system,
+ overriding a global configuration. [possible values: git, hg, pijul,
+ fossil, none]
--bin Use a binary (application) template [default]
--lib Use a library template
--edition <YEAR> Edition to set for the crate generated [possible values: 2015, 2018,
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_lints/mod.rs b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_lints/mod.rs
index 0b7697d20..9b9642468 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_lints/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_new/inherit_workspace_lints/mod.rs
@@ -1,7 +1,6 @@
use cargo_test_support::compare::assert_ui;
use cargo_test_support::curr_dir;
use cargo_test_support::CargoCommand;
-use cargo_test_support::ChannelChanger;
use cargo_test_support::Project;
#[cargo_test]
@@ -12,9 +11,8 @@ fn case() {
snapbox::cmd::Command::cargo_ui()
.arg("new")
- .args(["crates/foo", "-Zlints"])
+ .args(["crates/foo"])
.current_dir(cwd)
- .masquerade_as_nightly_cargo(&["lints"])
.assert()
.success()
.stdout_matches_path(curr_dir!().join("stdout.log"))
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/mod.rs b/src/tools/cargo/tests/testsuite/cargo_new/mod.rs
index 887316395..969b09f4f 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_new/mod.rs
@@ -4,4 +4,4 @@ mod inherit_workspace_package_table;
mod inherit_workspace_package_table_with_edition;
mod inherit_workspace_package_table_with_registry;
mod inherit_workspace_package_table_without_version;
-mod not_inherit_workspace_package_table_if_not_memebers;
+mod not_inherit_workspace_package_table_if_not_members;
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/Cargo.toml
index 2d204581c..2d204581c 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/Cargo.toml
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/README.md b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/README.md
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/README.md
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/src/lib.rs
index 7d12d9af8..7d12d9af8 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/in/src/lib.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/mod.rs b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/mod.rs
index cdddf0e64..cdddf0e64 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/mod.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/Cargo.toml
index 2d204581c..2d204581c 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/Cargo.toml
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/foo/Cargo.toml
index 4fcf77121..4fcf77121 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/Cargo.toml
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/foo/Cargo.toml
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/src/main.rs b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/foo/src/main.rs
index e7a11a969..e7a11a969 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/foo/src/main.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/foo/src/main.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/src/lib.rs
index 7d12d9af8..7d12d9af8 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/out/src/lib.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stderr.log b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/stderr.log
index 03b1ff6db..03b1ff6db 100644
--- a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_memebers/stderr.log
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/stderr.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/stdout.log b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_owner/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_owner/help/stdout.log
index 3c8495ff0..580be3c88 100644
--- a/src/tools/cargo/tests/testsuite/cargo_owner/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_owner/help/stdout.log
@@ -9,9 +9,9 @@ Options:
-a, --add <LOGIN> Name of a user or team to invite as an owner
-r, --remove <LOGIN> Name of a user or team to remove as an owner
-l, --list List owners of a crate
- --index <INDEX> Registry index to modify owners for
+ --index <INDEX> Registry index URL to modify owners for
+ --registry <REGISTRY> Registry to modify owners for
--token <TOKEN> API token to use when authenticating
- --registry <REGISTRY> Registry to use
-q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
--color <WHEN> Coloring: auto, always, never
diff --git a/src/tools/cargo/tests/testsuite/cargo_package/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_package/help/stdout.log
index 35e32f313..5079c2a6f 100644
--- a/src/tools/cargo/tests/testsuite/cargo_package/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_package/help/stdout.log
@@ -25,10 +25,10 @@ Feature Selection:
--no-default-features Do not activate the `default` feature
Compilation Options:
- --target <TRIPLE> Build for the target triple
+ --target [<TRIPLE>] Build for the target triple
--target-dir <DIRECTORY> Directory for all generated artifacts
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
- --keep-going Do not abort the build as soon as there is an error (unstable)
+ --keep-going Do not abort the build as soon as there is an error
Manifest Options:
--manifest-path <PATH> Path to Cargo.toml
diff --git a/src/tools/cargo/tests/testsuite/cargo_publish/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_publish/help/stdout.log
index c02522887..df2594fb4 100644
--- a/src/tools/cargo/tests/testsuite/cargo_publish/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_publish/help/stdout.log
@@ -3,9 +3,9 @@ Upload a package to the registry
Usage: cargo[EXE] publish [OPTIONS]
Options:
- --dry-run Perform all checks without uploading
+ -n, --dry-run Perform all checks without uploading
--index <INDEX> Registry index URL to upload the package to
- --registry <REGISTRY> Registry to publish to
+ --registry <REGISTRY> Registry to upload the package to
--token <TOKEN> Token to use when uploading
--no-verify Don't verify the contents by building them
--allow-dirty Allow dirty working directories to be packaged
@@ -26,8 +26,8 @@ Feature Selection:
Compilation Options:
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
- --keep-going Do not abort the build as soon as there is an error (unstable)
- --target <TRIPLE> Build for the target triple
+ --keep-going Do not abort the build as soon as there is an error
+ --target [<TRIPLE>] Build for the target triple
--target-dir <DIRECTORY> Directory for all generated artifacts
Manifest Options:
diff --git a/src/tools/cargo/tests/testsuite/cargo_remove/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_remove/help/stdout.log
index 81a2d78b6..8937fb9f3 100644
--- a/src/tools/cargo/tests/testsuite/cargo_remove/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_remove/help/stdout.log
@@ -6,7 +6,7 @@ Arguments:
<DEP_ID>... Dependencies to be removed
Options:
- --dry-run Don't actually write the manifest
+ -n, --dry-run Don't actually write the manifest
-q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
--color <WHEN> Coloring: auto, always, never
@@ -27,3 +27,5 @@ Manifest Options:
--frozen Require Cargo.lock and cache are up to date
--locked Require Cargo.lock is up to date
--offline Run without accessing the network
+
+Run `cargo help remove` for more detailed information.
diff --git a/src/tools/cargo/tests/testsuite/cargo_remove/mod.rs b/src/tools/cargo/tests/testsuite/cargo_remove/mod.rs
index ea7902bd8..4403e2425 100644
--- a/src/tools/cargo/tests/testsuite/cargo_remove/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_remove/mod.rs
@@ -23,6 +23,7 @@ mod optional_dep_feature;
mod optional_feature;
mod package;
mod remove_basic;
+mod skip_gc_glob_profile;
mod target;
mod target_build;
mod target_dev;
diff --git a/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/in/Cargo.toml
new file mode 100644
index 000000000..a25e33ae0
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/in/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "cargo-remove-test-fixture"
+version = "0.1.0"
+
+[[bin]]
+name = "main"
+path = "src/main.rs"
+
+[dependencies]
+toml = "0.1"
+
+[profile.dev.package."*"]
+opt-level = 3 \ No newline at end of file
diff --git a/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/in/src/lib.rs
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/in/src/lib.rs
@@ -0,0 +1 @@
+
diff --git a/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/mod.rs b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/mod.rs
new file mode 100644
index 000000000..2d587455c
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/mod.rs
@@ -0,0 +1,25 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::curr_dir;
+use cargo_test_support::CargoCommand;
+use cargo_test_support::Project;
+
+#[cargo_test]
+fn case() {
+ cargo_test_support::registry::init();
+ cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("remove")
+ .args(["toml"])
+ .current_dir(cwd)
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/out/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/out/Cargo.toml
new file mode 100644
index 000000000..76e3bcf77
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/out/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "cargo-remove-test-fixture"
+version = "0.1.0"
+
+[[bin]]
+name = "main"
+path = "src/main.rs"
+
+[profile.dev.package."*"]
+opt-level = 3
diff --git a/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/stderr.log b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/stderr.log
new file mode 100644
index 000000000..9dee9e2b7
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/stderr.log
@@ -0,0 +1 @@
+ Removing toml from dependencies
diff --git a/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/stdout.log b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_remove/skip_gc_glob_profile/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_run/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_run/help/stdout.log
index 6ab0e76b1..4b39f30b3 100644
--- a/src/tools/cargo/tests/testsuite/cargo_run/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_run/help/stdout.log
@@ -30,10 +30,10 @@ Feature Selection:
Compilation Options:
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
- --keep-going Do not abort the build as soon as there is an error (unstable)
+ --keep-going Do not abort the build as soon as there is an error
-r, --release Build artifacts in release mode, with optimizations
--profile <PROFILE-NAME> Build artifacts with the specified profile
- --target <TRIPLE> Build for the target triple
+ --target [<TRIPLE>] Build for the target triple
--target-dir <DIRECTORY> Directory for all generated artifacts
--unit-graph Output build graph in JSON (unstable)
--timings[=<FMTS>] Timing output formats (unstable) (comma separated): html, json
diff --git a/src/tools/cargo/tests/testsuite/cargo_rustc/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_rustc/help/stdout.log
index f587c3276..9d43841fe 100644
--- a/src/tools/cargo/tests/testsuite/cargo_rustc/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_rustc/help/stdout.log
@@ -41,10 +41,10 @@ Feature Selection:
Compilation Options:
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
- --keep-going Do not abort the build as soon as there is an error (unstable)
+ --keep-going Do not abort the build as soon as there is an error
-r, --release Build artifacts in release mode, with optimizations
--profile <PROFILE-NAME> Build artifacts with the specified profile
- --target <TRIPLE> Target triple which compiles will be for
+ --target [<TRIPLE>] Target triple which compiles will be for
--target-dir <DIRECTORY> Directory for all generated artifacts
--unit-graph Output build graph in JSON (unstable)
--timings[=<FMTS>] Timing output formats (unstable) (comma separated): html, json
diff --git a/src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stdout.log
index 4cac29e0a..706072f24 100644
--- a/src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_rustdoc/help/stdout.log
@@ -39,10 +39,10 @@ Feature Selection:
Compilation Options:
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
- --keep-going Do not abort the build as soon as there is an error (unstable)
+ --keep-going Do not abort the build as soon as there is an error
-r, --release Build artifacts in release mode, with optimizations
--profile <PROFILE-NAME> Build artifacts with the specified profile
- --target <TRIPLE> Build for the target triple
+ --target [<TRIPLE>] Build for the target triple
--target-dir <DIRECTORY> Directory for all generated artifacts
--unit-graph Output build graph in JSON (unstable)
--timings[=<FMTS>] Timing output formats (unstable) (comma separated): html, json
diff --git a/src/tools/cargo/tests/testsuite/cargo_search/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_search/help/stdout.log
index 8572064e3..07170ad70 100644
--- a/src/tools/cargo/tests/testsuite/cargo_search/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_search/help/stdout.log
@@ -7,8 +7,8 @@ Arguments:
Options:
--limit <LIMIT> Limit the number of results (default: 10, max: 100)
- --index <INDEX> Registry index URL to upload the package to
- --registry <REGISTRY> Registry to use
+ --index <INDEX> Registry index URL to search packages in
+ --registry <REGISTRY> Registry to search packages in
-q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
--color <WHEN> Coloring: auto, always, never
diff --git a/src/tools/cargo/tests/testsuite/cargo_test/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_test/help/stdout.log
index d693dc3c9..5df62d6bb 100644
--- a/src/tools/cargo/tests/testsuite/cargo_test/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_test/help/stdout.log
@@ -48,7 +48,7 @@ Compilation Options:
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs.
-r, --release Build artifacts in release mode, with optimizations
--profile <PROFILE-NAME> Build artifacts with the specified profile
- --target <TRIPLE> Build for the target triple
+ --target [<TRIPLE>] Build for the target triple
--target-dir <DIRECTORY> Directory for all generated artifacts
--unit-graph Output build graph in JSON (unstable)
--timings[=<FMTS>] Timing output formats (unstable) (comma separated): html, json
diff --git a/src/tools/cargo/tests/testsuite/cargo_test/mod.rs b/src/tools/cargo/tests/testsuite/cargo_test/mod.rs
index c0ce11180..28be9d1a7 100644
--- a/src/tools/cargo/tests/testsuite/cargo_test/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_test/mod.rs
@@ -1 +1,2 @@
mod help;
+mod no_keep_going;
diff --git a/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/in/Cargo.toml
new file mode 100644
index 000000000..c35d63273
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/in/Cargo.toml
@@ -0,0 +1,3 @@
+[package]
+name = "foo"
+version = "0.1.0"
diff --git a/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/in/src/lib.rs b/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/in/src/lib.rs
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/in/src/lib.rs
diff --git a/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/mod.rs b/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/mod.rs
new file mode 100644
index 000000000..fdec61642
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/mod.rs
@@ -0,0 +1,19 @@
+use cargo_test_support::curr_dir;
+use cargo_test_support::CargoCommand;
+use cargo_test_support::Project;
+
+#[cargo_test]
+fn case() {
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("test")
+ .arg("--keep-going")
+ .current_dir(cwd)
+ .assert()
+ .code(1)
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/stderr.log b/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/stderr.log
new file mode 100644
index 000000000..fd4ca9b2a
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/stderr.log
@@ -0,0 +1,7 @@
+error: unexpected argument '--keep-going' found
+
+ tip: use `--no-fail-fast` to run as many tests as possible regardless of failure
+
+Usage: cargo[EXE] test [OPTIONS] [TESTNAME] [-- [args]...]
+
+For more information, try '--help'.
diff --git a/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/stdout.log b/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_test/no_keep_going/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_tree/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_tree/help/stdout.log
index 268b6b2ad..4170583a8 100644
--- a/src/tools/cargo/tests/testsuite/cargo_tree/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_tree/help/stdout.log
@@ -33,8 +33,8 @@ Feature Selection:
--no-default-features Do not activate the `default` feature
Compilation Options:
- --target <TRIPLE> Filter dependencies matching the given target-triple (default host
- platform). Pass `all` to include all targets.
+ --target [<TRIPLE>] Filter dependencies matching the given target-triple (default host
+ platform). Pass `all` to include all targets.
Manifest Options:
--manifest-path <PATH> Path to Cargo.toml
diff --git a/src/tools/cargo/tests/testsuite/cargo_update/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_update/help/stdout.log
index 6cc109151..92caeb656 100644
--- a/src/tools/cargo/tests/testsuite/cargo_update/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_update/help/stdout.log
@@ -1,11 +1,11 @@
Update dependencies as recorded in the local lock file
-Usage: cargo[EXE] update [OPTIONS]
+Usage: cargo[EXE] update [OPTIONS] [SPEC]...
Options:
- --dry-run Don't actually write the lockfile
- --aggressive Force updating all dependencies of SPEC as well when used with -p
- --precise <PRECISE> Update a single dependency to exactly PRECISE when used with -p
+ -n, --dry-run Don't actually write the lockfile
+ --recursive Force updating all dependencies of [SPEC]... as well
+ --precise <PRECISE> Update [SPEC] to exactly PRECISE
-q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
--color <WHEN> Coloring: auto, always, never
@@ -14,8 +14,8 @@ Options:
-h, --help Print help
Package Selection:
- -w, --workspace Only update the workspace packages
- -p, --package [<SPEC>] Package to update
+ -w, --workspace Only update the workspace packages
+ [SPEC]... Package to update
Manifest Options:
--manifest-path <PATH> Path to Cargo.toml
diff --git a/src/tools/cargo/tests/testsuite/cargo_update/mod.rs b/src/tools/cargo/tests/testsuite/cargo_update/mod.rs
index c0ce11180..a809d9fe9 100644
--- a/src/tools/cargo/tests/testsuite/cargo_update/mod.rs
+++ b/src/tools/cargo/tests/testsuite/cargo_update/mod.rs
@@ -1 +1,2 @@
mod help;
+mod toolchain_pkgname;
diff --git a/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/in/Cargo.toml b/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/in/Cargo.toml
new file mode 100644
index 000000000..c844631b2
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/in/Cargo.toml
@@ -0,0 +1,5 @@
+[package]
+name = "test"
+version = "0.1.0"
+
+[dependencies]
diff --git a/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/in/src/main.rs b/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/in/src/main.rs
new file mode 100644
index 000000000..e7a11a969
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/in/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/mod.rs b/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/mod.rs
new file mode 100644
index 000000000..f1488b90d
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/mod.rs
@@ -0,0 +1,19 @@
+use cargo_test_support::curr_dir;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+#[cargo_test]
+fn case() {
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("update")
+ .arg("+stable")
+ .current_dir(cwd)
+ .assert()
+ .code(101)
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+}
diff --git a/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/stderr.log b/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/stderr.log
new file mode 100644
index 000000000..7e5870c54
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/stderr.log
@@ -0,0 +1,2 @@
+error: invalid character `+` in package name: `+stable`
+ Use `cargo +stable update` if you meant to use the `stable` toolchain.
diff --git a/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/stdout.log b/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/stdout.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/tools/cargo/tests/testsuite/cargo_update/toolchain_pkgname/stdout.log
diff --git a/src/tools/cargo/tests/testsuite/cargo_yank/help/stdout.log b/src/tools/cargo/tests/testsuite/cargo_yank/help/stdout.log
index 25b04e6c7..c6dbfeb9d 100644
--- a/src/tools/cargo/tests/testsuite/cargo_yank/help/stdout.log
+++ b/src/tools/cargo/tests/testsuite/cargo_yank/help/stdout.log
@@ -8,8 +8,8 @@ Arguments:
Options:
--version <VERSION> The version to yank or un-yank
--undo Undo a yank, putting a version back into the index
- --index <INDEX> Registry index to yank from
- --registry <REGISTRY> Registry to use
+ --index <INDEX> Registry index URL to yank from
+ --registry <REGISTRY> Registry to yank from
--token <TOKEN> API token to use when authenticating
-q, --quiet Do not print cargo log messages
-v, --verbose... Use verbose output (-vv very verbose/build.rs output)
diff --git a/src/tools/cargo/tests/testsuite/check.rs b/src/tools/cargo/tests/testsuite/check.rs
index 7bc9a38a3..b74bd6209 100644
--- a/src/tools/cargo/tests/testsuite/check.rs
+++ b/src/tools/cargo/tests/testsuite/check.rs
@@ -861,8 +861,7 @@ fn check_keep_going() {
.build();
// Due to -j1, without --keep-going only one of the two bins would be built.
- foo.cargo("check -j1 --keep-going -Zunstable-options")
- .masquerade_as_nightly_cargo(&["keep-going"])
+ foo.cargo("check -j1 --keep-going")
.with_status(101)
.with_stderr_contains("error: ONE")
.with_stderr_contains("error: TWO")
diff --git a/src/tools/cargo/tests/testsuite/clean.rs b/src/tools/cargo/tests/testsuite/clean.rs
index e0885fd26..fbb4d3e5b 100644
--- a/src/tools/cargo/tests/testsuite/clean.rs
+++ b/src/tools/cargo/tests/testsuite/clean.rs
@@ -272,7 +272,7 @@ fn clean_doc() {
assert!(doc_path.is_dir());
- p.cargo("clean --doc").run();
+ p.cargo("clean --doc").with_stderr("[REMOVED] [..]").run();
assert!(!doc_path.is_dir());
assert!(p.build_dir().is_dir());
@@ -414,9 +414,10 @@ fn clean_verbose() {
if cfg!(target_os = "macos") {
// Rust 1.69 has changed so that split-debuginfo=unpacked includes unpacked for rlibs.
for obj in p.glob("target/debug/deps/bar-*.o") {
- expected.push_str(&format!("[REMOVING] [..]{}", obj.unwrap().display()));
+ expected.push_str(&format!("[REMOVING] [..]{}\n", obj.unwrap().display()));
}
}
+ expected.push_str("[REMOVED] [..] files, [..] total\n");
p.cargo("clean -p bar --verbose")
.with_stderr_unordered(&expected)
.run();
@@ -569,10 +570,120 @@ fn assert_all_clean(build_dir: &Path) {
}
#[cargo_test]
-fn clean_spec_multiple() {
+fn clean_spec_version() {
// clean -p foo where foo matches multiple versions
- Package::new("bar", "1.0.0").publish();
- Package::new("bar", "2.0.0").publish();
+ Package::new("bar", "0.1.0").publish();
+ Package::new("bar", "0.2.0").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar1 = {version="0.1", package="bar"}
+ bar2 = {version="0.2", package="bar"}
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("build").run();
+
+ // Check suggestion for bad pkgid.
+ p.cargo("clean -p baz")
+ .with_status(101)
+ .with_stderr(
+ "\
+error: package ID specification `baz` did not match any packages
+
+<tab>Did you mean `bar`?
+",
+ )
+ .run();
+
+ p.cargo("clean -p bar:0.1.0")
+ .with_stderr(
+ "warning: version qualifier in `-p bar:0.1.0` is ignored, \
+ cleaning all versions of `bar` found\n\
+ [REMOVED] [..] files, [..] total",
+ )
+ .run();
+ let mut walker = walkdir::WalkDir::new(p.build_dir())
+ .into_iter()
+ .filter_map(|e| e.ok())
+ .filter(|e| {
+ let n = e.file_name().to_str().unwrap();
+ n.starts_with("bar") || n.starts_with("libbar")
+ });
+ if let Some(e) = walker.next() {
+ panic!("{:?} was not cleaned", e.path());
+ }
+}
+
+#[cargo_test]
+fn clean_spec_partial_version() {
+ // clean -p foo where foo matches multiple versions
+ Package::new("bar", "0.1.0").publish();
+ Package::new("bar", "0.2.0").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar1 = {version="0.1", package="bar"}
+ bar2 = {version="0.2", package="bar"}
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("build").run();
+
+ // Check suggestion for bad pkgid.
+ p.cargo("clean -p baz")
+ .with_status(101)
+ .with_stderr(
+ "\
+error: package ID specification `baz` did not match any packages
+
+<tab>Did you mean `bar`?
+",
+ )
+ .run();
+
+ p.cargo("clean -p bar:0.1")
+ .with_stderr(
+ "warning: version qualifier in `-p bar:0.1` is ignored, \
+ cleaning all versions of `bar` found\n\
+ [REMOVED] [..] files, [..] total",
+ )
+ .run();
+ let mut walker = walkdir::WalkDir::new(p.build_dir())
+ .into_iter()
+ .filter_map(|e| e.ok())
+ .filter(|e| {
+ let n = e.file_name().to_str().unwrap();
+ n.starts_with("bar") || n.starts_with("libbar")
+ });
+ if let Some(e) = walker.next() {
+ panic!("{:?} was not cleaned", e.path());
+ }
+}
+
+#[cargo_test]
+fn clean_spec_partial_version_ambiguous() {
+ // clean -p foo where foo matches multiple versions
+ Package::new("bar", "0.1.0").publish();
+ Package::new("bar", "0.2.0").publish();
let p = project()
.file(
@@ -583,8 +694,8 @@ fn clean_spec_multiple() {
version = "0.1.0"
[dependencies]
- bar1 = {version="1.0", package="bar"}
- bar2 = {version="2.0", package="bar"}
+ bar1 = {version="0.1", package="bar"}
+ bar2 = {version="0.2", package="bar"}
"#,
)
.file("src/lib.rs", "")
@@ -604,10 +715,11 @@ error: package ID specification `baz` did not match any packages
)
.run();
- p.cargo("clean -p bar:1.0.0")
+ p.cargo("clean -p bar:0")
.with_stderr(
- "warning: version qualifier in `-p bar:1.0.0` is ignored, \
- cleaning all versions of `bar` found",
+ "warning: version qualifier in `-p bar:0` is ignored, \
+ cleaning all versions of `bar` found\n\
+ [REMOVED] [..] files, [..] total",
)
.run();
let mut walker = walkdir::WalkDir::new(p.build_dir())
@@ -673,3 +785,72 @@ fn clean_spec_reserved() {
)
.run();
}
+
+#[cargo_test]
+fn clean_dry_run() {
+ // Basic `clean --dry-run` test.
+ Package::new("bar", "1.0.0").publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ let ls_r = || -> Vec<_> {
+ let mut file_list: Vec<_> = walkdir::WalkDir::new(p.build_dir())
+ .into_iter()
+ .filter_map(|e| e.map(|e| e.path().to_owned()).ok())
+ .collect();
+ file_list.sort();
+ file_list
+ };
+
+ // Start with no files.
+ p.cargo("clean --dry-run")
+ .with_stdout("")
+ .with_stderr(
+ "[SUMMARY] 0 files\n\
+ [WARNING] no files deleted due to --dry-run",
+ )
+ .run();
+ p.cargo("check").run();
+ let before = ls_r();
+ p.cargo("clean --dry-run")
+ .with_stderr(
+ "[SUMMARY] [..] files, [..] total\n\
+ [WARNING] no files deleted due to --dry-run",
+ )
+ .run();
+ // Verify it didn't delete anything.
+ let after = ls_r();
+ assert_eq!(before, after);
+ let expected = cargo::util::iter_join(before.iter().map(|p| p.to_str().unwrap()), "\n");
+ eprintln!("{expected}");
+ // Verify the verbose output.
+ p.cargo("clean --dry-run -v")
+ .with_stdout_unordered(expected)
+ .with_stderr(
+ "[SUMMARY] [..] files, [..] total\n\
+ [WARNING] no files deleted due to --dry-run",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn doc_with_package_selection() {
+ // --doc with -p
+ let p = project().file("src/lib.rs", "").build();
+ p.cargo("clean --doc -p foo")
+ .with_status(101)
+ .with_stderr("error: --doc cannot be used with -p")
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/config.rs b/src/tools/cargo/tests/testsuite/config.rs
index 5d4163818..7078fc445 100644
--- a/src/tools/cargo/tests/testsuite/config.rs
+++ b/src/tools/cargo/tests/testsuite/config.rs
@@ -541,18 +541,18 @@ expected boolean, but found array",
config.get::<VSOB>("b").unwrap(),
VSOB::VecString(vec![
"b".to_string(),
- "clib".to_string(),
"env1".to_string(),
- "env2".to_string()
+ "env2".to_string(),
+ "clib".to_string(),
])
);
assert_eq!(
config.get::<VSOB>("c").unwrap(),
VSOB::VecString(vec![
"c".to_string(),
- "clic".to_string(),
"e1".to_string(),
- "e2".to_string()
+ "e2".to_string(),
+ "clic".to_string(),
])
);
}
@@ -722,9 +722,6 @@ Caused by:
could not parse TOML configuration in `[..]/.cargo/config`
Caused by:
- could not parse input as TOML
-
-Caused by:
TOML parse error at line 1, column 5
|
1 | asdf
@@ -1091,9 +1088,6 @@ Caused by:
could not parse TOML configuration in `[..]/.cargo/config`
Caused by:
- could not parse input as TOML
-
-Caused by:
TOML parse error at line 3, column 1
|
3 | ssl-version.min = 'tlsv1.2'
@@ -1582,12 +1576,12 @@ known-hosts = [
.as_ref()
.unwrap();
assert_eq!(kh.len(), 4);
- assert_eq!(kh[0].val, "example.org ...");
- assert_eq!(kh[0].definition, Definition::Path(foo_path.clone()));
- assert_eq!(kh[1].val, "example.com ...");
+ assert_eq!(kh[0].val, "example.com ...");
+ assert_eq!(kh[0].definition, Definition::Path(root_path.clone()));
+ assert_eq!(kh[1].val, "example.net ...");
assert_eq!(kh[1].definition, Definition::Path(root_path.clone()));
- assert_eq!(kh[2].val, "example.net ...");
- assert_eq!(kh[2].definition, Definition::Path(root_path.clone()));
+ assert_eq!(kh[2].val, "example.org ...");
+ assert_eq!(kh[2].definition, Definition::Path(foo_path.clone()));
assert_eq!(kh[3].val, "env-example");
assert_eq!(
kh[3].definition,
diff --git a/src/tools/cargo/tests/testsuite/config_cli.rs b/src/tools/cargo/tests/testsuite/config_cli.rs
index 1120e279d..67aca0d19 100644
--- a/src/tools/cargo/tests/testsuite/config_cli.rs
+++ b/src/tools/cargo/tests/testsuite/config_cli.rs
@@ -143,11 +143,9 @@ fn merges_array() {
.env("CARGO_BUILD_RUSTFLAGS", "--env1 --env2")
.config_arg("build.rustflags = ['--cli']")
.build();
- // The order of cli/env is a little questionable here, but would require
- // much more complex merging logic.
assert_eq!(
config.get::<Vec<String>>("build.rustflags").unwrap(),
- ["--file", "--cli", "--env1", "--env2"]
+ ["--file", "--env1", "--env2", "--cli"]
);
// With advanced-env.
@@ -158,7 +156,7 @@ fn merges_array() {
.build();
assert_eq!(
config.get::<Vec<String>>("build.rustflags").unwrap(),
- ["--file", "--cli", "--env"]
+ ["--file", "--env", "--cli"]
);
// Merges multiple instances.
@@ -202,7 +200,7 @@ fn string_list_array() {
.get::<cargo::util::config::StringList>("build.rustflags")
.unwrap()
.as_slice(),
- ["--file", "--cli", "--env1", "--env2"]
+ ["--file", "--env1", "--env2", "--cli"]
);
// With advanced-env.
@@ -216,7 +214,7 @@ fn string_list_array() {
.get::<cargo::util::config::StringList>("build.rustflags")
.unwrap()
.as_slice(),
- ["--file", "--cli", "--env"]
+ ["--file", "--env", "--cli"]
);
}
diff --git a/src/tools/cargo/tests/testsuite/credential_process.rs b/src/tools/cargo/tests/testsuite/credential_process.rs
index c010c01cd..815089f70 100644
--- a/src/tools/cargo/tests/testsuite/credential_process.rs
+++ b/src/tools/cargo/tests/testsuite/credential_process.rs
@@ -7,63 +7,6 @@ fn toml_bin(proj: &Project, name: &str) -> String {
proj.bin(name).display().to_string().replace('\\', "\\\\")
}
-#[cargo_test]
-fn gated() {
- let _alternative = registry::RegistryBuilder::new()
- .alternative()
- .no_configure_token()
- .build();
-
- let cratesio = registry::RegistryBuilder::new()
- .no_configure_token()
- .build();
-
- let p = project()
- .file(
- ".cargo/config",
- r#"
- [registry]
- credential-provider = ["false"]
- "#,
- )
- .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
- .file("src/lib.rs", "")
- .build();
-
- p.cargo("publish --no-verify")
- .replace_crates_io(cratesio.index_url())
- .masquerade_as_nightly_cargo(&["credential-process"])
- .with_status(101)
- .with_stderr(
- "\
-[UPDATING] [..]
-[ERROR] no token found, please run `cargo login`
-or use environment variable CARGO_REGISTRY_TOKEN
-",
- )
- .run();
-
- p.change_file(
- ".cargo/config",
- r#"
- [registry.alternative]
- credential-process = "false"
- "#,
- );
-
- p.cargo("publish --no-verify --registry alternative")
- .masquerade_as_nightly_cargo(&["credential-process"])
- .with_status(101)
- .with_stderr(
- "\
-[UPDATING] [..]
-[ERROR] no token found for `alternative`, please run `cargo login --registry alternative`
-or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN
-",
- )
- .run();
-}
-
/// Setup for a test that will issue a command that needs to fetch a token.
///
/// This does the following:
@@ -125,14 +68,13 @@ fn publish() {
// Checks that credential-process is used for `cargo publish`.
let (p, _t) = get_token_test();
- p.cargo("publish --no-verify --registry alternative -Z credential-process -Z registry-auth")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ p.cargo("publish --no-verify --registry alternative")
.with_stderr(
r#"[UPDATING] [..]
-{"v":1,"registry":{"index-url":"[..]","name":"alternative","headers":[..]},"kind":"get","operation":"read","args":[]}
+{"v":1,"registry":{"index-url":"[..]","name":"alternative","headers":[..]},"kind":"get","operation":"read"}
[PACKAGING] foo v0.1.0 [..]
[PACKAGED] [..]
-{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"publish","name":"foo","vers":"0.1.0","cksum":"[..]","args":[]}
+{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"publish","name":"foo","vers":"0.1.0","cksum":"[..]"}
[UPLOADING] foo v0.1.0 [..]
[UPLOADED] foo v0.1.0 [..]
note: Waiting [..]
@@ -151,9 +93,8 @@ fn basic_unsupported() {
.credential_provider(&["cargo:token-from-stdout", "false"])
.build();
- cargo_process("login -Z credential-process abcdefg")
+ cargo_process("login abcdefg")
.replace_crates_io(registry.index_url())
- .masquerade_as_nightly_cargo(&["credential-process"])
.with_status(101)
.with_stderr(
"\
@@ -166,9 +107,8 @@ Caused by:
)
.run();
- cargo_process("logout -Z credential-process")
+ cargo_process("logout")
.replace_crates_io(registry.index_url())
- .masquerade_as_nightly_cargo(&["credential-process"])
.with_status(101)
.with_stderr(
"\
@@ -192,8 +132,7 @@ fn login() {
])
.build();
- cargo_process("login -Z credential-process abcdefg -- cmd3 --cmd4")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ cargo_process("login abcdefg -- cmd3 --cmd4")
.replace_crates_io(registry.index_url())
.with_stderr(
r#"[UPDATING] [..]
@@ -213,11 +152,10 @@ fn logout() {
)])
.build();
- cargo_process("logout -Z credential-process")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ cargo_process("logout")
.replace_crates_io(server.index_url())
.with_stderr(
- r#"{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"logout","args":[]}
+ r#"{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"logout"}
"#,
)
.run();
@@ -227,12 +165,11 @@ fn logout() {
fn yank() {
let (p, _t) = get_token_test();
- p.cargo("yank --version 0.1.0 --registry alternative -Zcredential-process -Zregistry-auth")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ p.cargo("yank --version 0.1.0 --registry alternative")
.with_stderr(
r#"[UPDATING] [..]
-{"v":1,"registry":{"index-url":"[..]","name":"alternative","headers":[..]},"kind":"get","operation":"read","args":[]}
-{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"yank","name":"foo","vers":"0.1.0","args":[]}
+{"v":1,"registry":{"index-url":"[..]","name":"alternative","headers":[..]},"kind":"get","operation":"read"}
+{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"yank","name":"foo","vers":"0.1.0"}
[YANK] foo@0.1.0
"#,
)
@@ -243,12 +180,11 @@ fn yank() {
fn owner() {
let (p, _t) = get_token_test();
- p.cargo("owner --add username --registry alternative -Zcredential-process -Zregistry-auth")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ p.cargo("owner --add username --registry alternative")
.with_stderr(
r#"[UPDATING] [..]
-{"v":1,"registry":{"index-url":"[..]","name":"alternative","headers":[..]},"kind":"get","operation":"read","args":[]}
-{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"owners","name":"foo","args":[]}
+{"v":1,"registry":{"index-url":"[..]","name":"alternative","headers":[..]},"kind":"get","operation":"read"}
+{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"owners","name":"foo"}
[OWNER] completed!
"#,
)
@@ -278,8 +214,7 @@ fn invalid_token_output() {
.file("src/lib.rs", "")
.build();
- p.cargo("publish --no-verify --registry alternative -Z credential-process")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ p.cargo("publish --no-verify --registry alternative")
.with_status(101)
.with_stderr(
"\
@@ -321,6 +256,35 @@ fn build_provider(name: &str, response: &str) -> String {
}
#[cargo_test]
+fn not_found() {
+ let registry = registry::RegistryBuilder::new()
+ .no_configure_token()
+ .http_index()
+ .auth_required()
+ .credential_provider(&[&build_provider(
+ "not_found",
+ r#"{"Err": {"kind": "not-found"}}"#,
+ )])
+ .build();
+
+ // should not suggest a _TOKEN environment variable since the cargo:token provider isn't available.
+ cargo_process("install -v foo")
+ .replace_crates_io(registry.index_url())
+ .with_status(101)
+ .with_stderr(
+ r#"[UPDATING] [..]
+[CREDENTIAL] [..]not_found[..] get crates-io
+{"v":1[..]
+[ERROR] failed to query replaced source registry `crates-io`
+
+Caused by:
+ no token found, please run `cargo login`
+"#,
+ )
+ .run();
+}
+
+#[cargo_test]
fn all_not_found() {
let server = registry::RegistryBuilder::new()
.no_configure_token()
@@ -342,19 +306,18 @@ fn all_not_found() {
)
.unwrap();
- cargo_process("install -v foo -Zcredential-process -Zregistry-auth")
- .masquerade_as_nightly_cargo(&["credential-process", "registry-auth"])
+ // should not suggest a _TOKEN environment variable since the cargo:token provider isn't available.
+ cargo_process("install -v foo")
.replace_crates_io(server.index_url())
.with_status(101)
.with_stderr(
r#"[UPDATING] [..]
[CREDENTIAL] [..]not_found[..] get crates-io
-{"v":1,"registry":{"index-url":"[..]","name":"crates-io","headers":[[..]"WWW-Authenticate: Cargo login_url=\"https://test-registry-login/me\""[..]]},"kind":"get","operation":"read","args":[]}
+{"v":1,"registry":{"index-url":"[..]","name":"crates-io","headers":[[..]"WWW-Authenticate: Cargo login_url=\"https://test-registry-login/me\""[..]]},"kind":"get","operation":"read"}
[ERROR] failed to query replaced source registry `crates-io`
Caused by:
no token found, please run `cargo login`
- or use environment variable CARGO_REGISTRY_TOKEN
"#,
)
.run();
@@ -383,14 +346,13 @@ fn all_not_supported() {
)
.unwrap();
- cargo_process("install -v foo -Zcredential-process -Zregistry-auth")
- .masquerade_as_nightly_cargo(&["credential-process", "registry-auth"])
+ cargo_process("install -v foo")
.replace_crates_io(server.index_url())
.with_status(101)
.with_stderr(
r#"[UPDATING] [..]
[CREDENTIAL] [..]not_supported[..] get crates-io
-{"v":1,"registry":{"index-url":"[..]","name":"crates-io","headers":[[..]"WWW-Authenticate: Cargo login_url=\"https://test-registry-login/me\""[..]]},"kind":"get","operation":"read","args":[]}
+{"v":1,"registry":{"index-url":"[..]","name":"crates-io","headers":[[..]"WWW-Authenticate: Cargo login_url=\"https://test-registry-login/me\""[..]]},"kind":"get","operation":"read"}
[ERROR] failed to query replaced source registry `crates-io`
Caused by:
@@ -431,15 +393,14 @@ fn multiple_providers() {
)
.unwrap();
- cargo_process("login -Z credential-process -v abcdefg")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ cargo_process("login -v abcdefg")
.replace_crates_io(server.index_url())
.with_stderr(
r#"[UPDATING] [..]
[CREDENTIAL] [..]url_not_supported[..] login crates-io
-{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"login","token":"abcdefg","login-url":"[..]","args":[]}
+{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"login","token":"abcdefg","login-url":"[..]"}
[CREDENTIAL] [..]success_provider[..] login crates-io
-{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"login","token":"abcdefg","login-url":"[..]","args":[]}
+{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"login","token":"abcdefg","login-url":"[..]"}
"#,
)
.run();
@@ -447,25 +408,42 @@ fn multiple_providers() {
#[cargo_test]
fn both_token_and_provider() {
+ let server = registry::RegistryBuilder::new()
+ .credential_provider(&["cargo:paseto"])
+ .build();
+
+ cargo_process("login -Z asymmetric-token")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
+ .replace_crates_io(server.index_url())
+ .with_stderr(
+ r#"[UPDATING] [..]
+[WARNING] registry `crates-io` has a token configured in [..] that will be ignored because this registry is configured to use credential-provider `cargo:paseto`
+k3.public[..]
+"#,
+ )
+ .run();
+}
+
+#[cargo_test]
+fn registry_provider_overrides_global() {
let server = registry::RegistryBuilder::new().build();
cargo_util::paths::append(
&paths::home().join(".cargo/config"),
format!(
r#"
[registry]
- credential-provider = ["cargo:token"]
+ global-credential-providers = ["should-not-be-called"]
"#,
)
.as_bytes(),
)
.unwrap();
- cargo_process("login -Z credential-process -v abcdefg")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ cargo_process("login -v abcdefg")
+ .env("CARGO_REGISTRY_CREDENTIAL_PROVIDER", "cargo:token")
.replace_crates_io(server.index_url())
.with_stderr(
r#"[UPDATING] [..]
-[WARNING] registry `crates-io` has a token configured in [..]credentials.toml that will be ignored because a credential-provider is configured for this registry`
[CREDENTIAL] cargo:token login crates-io
[LOGIN] token for `crates-io` saved
"#,
@@ -492,8 +470,8 @@ fn both_asymmetric_and_token() {
)
.unwrap();
- cargo_process("login -Z credential-process -v abcdefg")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ cargo_process("login -Zasymmetric-token -v abcdefg")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
.replace_crates_io(server.index_url())
.with_stderr(
r#"[UPDATING] [..]
@@ -520,13 +498,13 @@ fn token_caching() {
// Token should not be re-used if it is expired
let expired_provider = build_provider(
- "test-cred",
- r#"{"Ok":{"kind":"get","token":"sekrit","cache":{"expires":0},"operation_independent":true}}"#,
+ "expired_provider",
+ r#"{"Ok":{"kind":"get","token":"sekrit","cache":"expires","expiration":0,"operation_independent":true}}"#,
);
// Token should not be re-used for a different operation if it is not operation_independent
let non_independent_provider = build_provider(
- "test-cred",
+ "non_independent_provider",
r#"{"Ok":{"kind":"get","token":"sekrit","cache":"session","operation_independent":false}}"#,
);
@@ -557,10 +535,10 @@ fn token_caching() {
.build();
let output = r#"[UPDATING] `alternative` index
-{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"read","args":[]}
+{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"read"}
[PACKAGING] foo v0.1.0 [..]
[PACKAGED] [..]
-{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"publish","name":"foo","vers":"0.1.0","cksum":"[..]","args":[]}
+{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"publish","name":"foo","vers":"0.1.0","cksum":"[..]"}
[UPLOADING] foo v0.1.0 [..]
[UPLOADED] foo v0.1.0 [..]
note: Waiting [..]
@@ -568,11 +546,10 @@ You may press ctrl-c [..]
[PUBLISHED] foo v0.1.0 [..]
"#;
- // The output should contain two JSON messages from the provider in boths cases:
+ // The output should contain two JSON messages from the provider in both cases:
// The first because the credential is expired, the second because the provider
// indicated that the token was non-operation-independent.
- p.cargo("publish -Z credential-process --registry alternative --no-verify")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ p.cargo("publish --registry alternative --no-verify")
.with_stderr(output)
.run();
@@ -588,8 +565,7 @@ You may press ctrl-c [..]
),
);
- p.cargo("publish -Z credential-process --registry alternative --no-verify")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ p.cargo("publish --registry alternative --no-verify")
.with_stderr(output)
.run();
}
@@ -639,8 +615,7 @@ fn basic_provider() {
.build();
Package::new("bar", "0.0.1").alternative(true).publish();
- p.cargo("check -Z credential-process -Z registry-auth")
- .masquerade_as_nightly_cargo(&["credential-process", "registry-auth"])
+ p.cargo("check")
.with_stderr(
"\
[UPDATING] `alternative` index
@@ -656,3 +631,72 @@ CARGO_REGISTRY_INDEX_URL=Some([..])
)
.run();
}
+
+#[cargo_test]
+fn unsupported_version() {
+ let cred_proj = project()
+ .at("new-vers")
+ .file("Cargo.toml", &basic_manifest("new-vers", "1.0.0"))
+ .file(
+ "src/main.rs",
+ &r####"
+ fn main() {
+ println!(r#"{{"v":[998, 999]}}"#);
+ assert_eq!(std::env::args().skip(1).next().unwrap(), "--cargo-plugin");
+ let mut buffer = String::new();
+ std::io::stdin().read_line(&mut buffer).unwrap();
+ std::thread::sleep(std::time::Duration::from_secs(1));
+ panic!("child process should have been killed before getting here");
+ } "####,
+ )
+ .build();
+ cred_proj.cargo("build").run();
+ let provider = toml_bin(&cred_proj, "new-vers");
+
+ let registry = registry::RegistryBuilder::new()
+ .no_configure_token()
+ .credential_provider(&[&provider])
+ .build();
+
+ cargo_process("login abcdefg")
+ .replace_crates_io(registry.index_url())
+ .with_status(101)
+ .with_stderr(
+ r#"[UPDATING] [..]
+[ERROR] credential provider `[..]` failed action `login`
+
+Caused by:
+ credential provider supports protocol versions [998, 999], while Cargo supports [1]
+"#,
+ )
+ .run();
+}
+
+#[cargo_test]
+fn alias_builtin_warning() {
+ let registry = registry::RegistryBuilder::new()
+ .credential_provider(&[&"cargo:token"])
+ .build();
+
+ cargo_util::paths::append(
+ &paths::home().join(".cargo/config"),
+ format!(
+ r#"
+ [credential-alias]
+ "cargo:token" = ["ignored"]
+ "#,
+ )
+ .as_bytes(),
+ )
+ .unwrap();
+
+ cargo_process("login abcdefg")
+ .replace_crates_io(registry.index_url())
+ .with_stderr(
+ r#"[UPDATING] [..]
+[WARNING] credential-alias `cargo:token` (defined in `[..]`) will be ignored because it would shadow a built-in credential-provider
+[LOGIN] token for `crates-io` saved
+"#,
+ )
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/doc.rs b/src/tools/cargo/tests/testsuite/doc.rs
index 481df8590..a16980912 100644
--- a/src/tools/cargo/tests/testsuite/doc.rs
+++ b/src/tools/cargo/tests/testsuite/doc.rs
@@ -2004,7 +2004,7 @@ fn crate_versions() {
let output_path = p.root().join("target/doc/foo/index.html");
let output_documentation = fs::read_to_string(&output_path).unwrap();
- assert!(output_documentation.contains("Version 1.2.4"));
+ assert!(output_documentation.contains("1.2.4"));
}
#[cargo_test]
@@ -2028,7 +2028,7 @@ fn crate_versions_flag_is_overridden() {
};
let asserts = |html: String| {
assert!(!html.contains("1.2.4"));
- assert!(html.contains("Version 2.0.3"));
+ assert!(html.contains("2.0.3"));
};
p.cargo("doc")
diff --git a/src/tools/cargo/tests/testsuite/features2.rs b/src/tools/cargo/tests/testsuite/features2.rs
index 68fecb863..9238de2c6 100644
--- a/src/tools/cargo/tests/testsuite/features2.rs
+++ b/src/tools/cargo/tests/testsuite/features2.rs
@@ -1431,9 +1431,10 @@ fn edition_2021_workspace_member() {
p.cargo("check")
.with_stderr(
"\
-warning: some crates are on edition 2021 which defaults to `resolver = \"2\"`, but virtual workspaces default to `resolver = \"1\"`
+warning: virtual workspace defaulting to `resolver = \"1\"` despite one or more workspace members being on edition 2021 which implies `resolver = \"2\"`
note: to keep the current resolver, specify `workspace.resolver = \"1\"` in the workspace root's manifest
note: to use the edition 2021 resolver, specify `workspace.resolver = \"2\"` in the workspace root's manifest
+note: for more details see https://doc.rust-lang.org/cargo/reference/resolver.html#resolver-versions
[CHECKING] a v0.1.0 [..]
[FINISHED] [..]
",
diff --git a/src/tools/cargo/tests/testsuite/freshness.rs b/src/tools/cargo/tests/testsuite/freshness.rs
index f28f1ff46..d450cbbd9 100644
--- a/src/tools/cargo/tests/testsuite/freshness.rs
+++ b/src/tools/cargo/tests/testsuite/freshness.rs
@@ -2786,7 +2786,7 @@ fn verify_source_before_recompile() {
"vendor/bar/src/lib.rs",
r#"compile_error!("You shall not pass!");"#,
);
- // Should ignore modifed sources without any recompile.
+ // Should ignore modified sources without any recompile.
p.cargo("check --verbose")
.with_stderr(
"\
@@ -2799,7 +2799,7 @@ fn verify_source_before_recompile() {
// Add a `RUSTFLAGS` to trigger a recompile.
//
- // Cargo should refuse to build because of checksum verfication failure.
+ // Cargo should refuse to build because of checksum verification failure.
// Cargo shouldn't recompile dependency `bar`.
p.cargo("check --verbose")
.env("RUSTFLAGS", "-W warnings")
diff --git a/src/tools/cargo/tests/testsuite/future_incompat_report.rs b/src/tools/cargo/tests/testsuite/future_incompat_report.rs
index 4d2c66d17..c52bf25a9 100644
--- a/src/tools/cargo/tests/testsuite/future_incompat_report.rs
+++ b/src/tools/cargo/tests/testsuite/future_incompat_report.rs
@@ -369,7 +369,7 @@ fn suggestions_for_updates() {
// project or something). This could use some more consideration of how to
// handle this better (maybe only trigger an update if it hasn't updated
// in a long while?).
- p.cargo("update -p without_updates").run();
+ p.cargo("update without_updates").run();
let update_message = "\
- Some affected dependencies have newer versions available.
diff --git a/src/tools/cargo/tests/testsuite/git.rs b/src/tools/cargo/tests/testsuite/git.rs
index f60ee978a..e27315346 100644
--- a/src/tools/cargo/tests/testsuite/git.rs
+++ b/src/tools/cargo/tests/testsuite/git.rs
@@ -742,11 +742,11 @@ fn update_with_shared_deps() {
// By default, not transitive updates
println!("dep1 update");
- p.cargo("update -p dep1").with_stdout("").run();
+ p.cargo("update dep1").with_stdout("").run();
// Don't do anything bad on a weird --precise argument
println!("bar bad precise update");
- p.cargo("update -p bar --precise 0.1.2")
+ p.cargo("update bar --precise 0.1.2")
.with_status(101)
.with_stderr(
"\
@@ -764,14 +764,14 @@ Caused by:
// Specifying a precise rev to the old rev shouldn't actually update
// anything because we already have the rev in the db.
println!("bar precise update");
- p.cargo("update -p bar --precise")
+ p.cargo("update bar --precise")
.arg(&old_head.to_string())
.with_stdout("")
.run();
- // Updating aggressively should, however, update the repo.
- println!("dep1 aggressive update");
- p.cargo("update -p dep1 --aggressive")
+ // Updating recursively should, however, update the repo.
+ println!("dep1 recursive update");
+ p.cargo("update dep1 --recursive")
.with_stderr(&format!(
"[UPDATING] git repository `{}`\n\
[UPDATING] bar v0.5.0 ([..]) -> #[..]\n\
@@ -795,7 +795,7 @@ Caused by:
.run();
// We should be able to update transitive deps
- p.cargo("update -p bar")
+ p.cargo("update bar")
.with_stderr(&format!(
"[UPDATING] git repository `{}`",
git_project.url()
@@ -1183,7 +1183,7 @@ fn two_deps_only_update_one() {
let oid = git::commit(&repo);
println!("dep1 head sha: {}", oid_to_short_sha(oid));
- p.cargo("update -p dep1")
+ p.cargo("update dep1")
.with_stderr(&format!(
"[UPDATING] git repository `{}`\n\
[UPDATING] dep1 v0.5.0 ([..]) -> #[..]\n\
@@ -1881,14 +1881,14 @@ fn update_ambiguous() {
.build();
p.cargo("generate-lockfile").run();
- p.cargo("update -p bar")
+ p.cargo("update bar")
.with_status(101)
.with_stderr(
"\
[ERROR] There are multiple `bar` packages in your project, and the specification `bar` \
is ambiguous.
-Please re-run this command with `-p <spec>` where `<spec>` is one of the \
-following:
+Please re-run this command with one of the \
+following specifications:
bar@0.[..].0
bar@0.[..].0
",
@@ -1928,7 +1928,7 @@ fn update_one_dep_in_repo_with_many_deps() {
.build();
p.cargo("generate-lockfile").run();
- p.cargo("update -p bar")
+ p.cargo("update bar")
.with_stderr(&format!("[UPDATING] git repository `{}`", bar.url()))
.run();
}
@@ -2091,7 +2091,7 @@ fn update_one_source_updates_all_packages_in_that_git_source() {
git::add(&repo);
git::commit(&repo);
- p.cargo("update -p dep").run();
+ p.cargo("update dep").run();
let lockfile = p.read_lockfile();
assert!(
!lockfile.contains(&rev1.to_string()),
@@ -2578,9 +2578,6 @@ Caused by:
failed to parse manifest at `[..]`
Caused by:
- could not parse input as TOML
-
-Caused by:
TOML parse error at line 8, column 21
|
8 | categories = [\"algorithms\"]
diff --git a/src/tools/cargo/tests/testsuite/inheritable_workspace_fields.rs b/src/tools/cargo/tests/testsuite/inheritable_workspace_fields.rs
index cc261a47f..47437102a 100644
--- a/src/tools/cargo/tests/testsuite/inheritable_workspace_fields.rs
+++ b/src/tools/cargo/tests/testsuite/inheritable_workspace_fields.rs
@@ -1234,8 +1234,11 @@ fn error_workspace_false() {
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
Caused by:
+ TOML parse error at line 7, column 41
+ |
+ 7 | description = { workspace = false }
+ | ^^^^^
`workspace` cannot be false
- in `package.description.workspace`
",
)
.run();
@@ -1323,9 +1326,6 @@ fn error_malformed_workspace_root() {
Caused by:
[..]
-
-Caused by:
- [..]
|
3 | members = [invalid toml
| ^
diff --git a/src/tools/cargo/tests/testsuite/install.rs b/src/tools/cargo/tests/testsuite/install.rs
index 0c7fc5037..0a3670e6c 100644
--- a/src/tools/cargo/tests/testsuite/install.rs
+++ b/src/tools/cargo/tests/testsuite/install.rs
@@ -72,6 +72,18 @@ fn toolchain() {
}
#[cargo_test]
+fn url() {
+ pkg("foo", "0.0.1");
+ cargo_process("install https://github.com/bar/foo")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] invalid package name: `https://github.com/bar/foo`
+ Use `cargo install --git https://github.com/bar/foo` if you meant to install from a git repository.")
+ .run();
+}
+
+#[cargo_test]
fn simple_with_message_format() {
pkg("foo", "0.0.1");
@@ -1600,8 +1612,13 @@ fn inline_version_without_name() {
pkg("foo", "0.1.2");
cargo_process("install @0.1.1")
- .with_status(101)
- .with_stderr("error: missing crate name for `@0.1.1`")
+ .with_status(1)
+ .with_stderr(
+ "error: invalid value '@0.1.1' for '[crate]...': missing crate name before '@'
+
+For more information, try '--help'.
+",
+ )
.run();
}
@@ -1612,7 +1629,7 @@ fn inline_and_explicit_version() {
cargo_process("install foo@0.1.1 --version 0.1.1")
.with_status(101)
- .with_stderr("error: cannot specify both `@0.1.1` and `--version`")
+ .with_stderr("error: cannot specify both `@<VERSION>` and `--version <VERSION>`")
.run();
}
@@ -1827,7 +1844,7 @@ fn install_empty_argument() {
cargo_process("install")
.arg("")
.with_status(1)
- .with_stderr_contains("[ERROR] a value is required for '[crate]...' but none was supplied")
+ .with_stderr_contains("[ERROR] invalid value '' for '[crate]...': crate name is empty")
.run();
}
@@ -2275,9 +2292,9 @@ fn failed_install_retains_temp_directory() {
.unwrap();
// Find the path in the output.
- let start = stderr.find("found at `").unwrap() + 10;
- let end = stderr[start..].find('.').unwrap() - 1;
- let path = Path::new(&stderr[start..(end + start)]);
+ let stderr = stderr.split_once("found at `").unwrap().1;
+ let end = stderr.find('.').unwrap() - 1;
+ let path = Path::new(&stderr[..end]);
assert!(path.exists());
assert!(path.join("release/deps").exists());
}
@@ -2426,3 +2443,23 @@ fn ambiguous_registry_vs_local_package() {
.run();
assert_has_installed_exe(cargo_home(), "foo");
}
+
+#[cargo_test]
+fn install_with_redundant_default_mode() {
+ pkg("foo", "0.0.1");
+
+ cargo_process("install foo --release")
+ .with_stderr(
+ "\
+error: unexpected argument '--release' found
+
+ tip: `--release` is the default for `cargo install`; instead `--debug` is supported
+
+Usage: cargo[EXE] install [OPTIONS] [crate]...
+
+For more information, try '--help'.
+",
+ )
+ .with_status(1)
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/install_upgrade.rs b/src/tools/cargo/tests/testsuite/install_upgrade.rs
index ae641ba98..580117f5c 100644
--- a/src/tools/cargo/tests/testsuite/install_upgrade.rs
+++ b/src/tools/cargo/tests/testsuite/install_upgrade.rs
@@ -230,12 +230,14 @@ fn ambiguous_version_no_longer_allowed() {
cargo_process("install foo --version=1.0")
.with_stderr(
"\
-[ERROR] the `--version` provided, `1.0`, is not a valid semver version: cannot parse '1.0' as a semver
+[ERROR] invalid value '1.0' for '--version <VERSION>': cannot parse '1.0' as a SemVer version
-if you want to specify semver range, add an explicit qualifier, like ^1.0
+ tip: if you want to specify SemVer range, add an explicit qualifier, like '^1.0'
+
+For more information, try '--help'.
",
)
- .with_status(101)
+ .with_status(1)
.run();
}
diff --git a/src/tools/cargo/tests/testsuite/lints.rs b/src/tools/cargo/tests/testsuite/lints.rs
index 854de69e9..21139d00a 100644
--- a/src/tools/cargo/tests/testsuite/lints.rs
+++ b/src/tools/cargo/tests/testsuite/lints.rs
@@ -4,72 +4,6 @@ use cargo_test_support::project;
use cargo_test_support::registry::Package;
#[cargo_test]
-fn package_requires_option() {
- let foo = project()
- .file(
- "Cargo.toml",
- r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [lints.rust]
- unsafe_code = "forbid"
- "#,
- )
- .file("src/lib.rs", "")
- .build();
-
- foo.cargo("check")
- .with_stderr(
- "\
-warning: unused manifest key `lints` (may be supported in a future version)
-
-this Cargo does not support nightly features, but if you
-switch to nightly channel you can pass
-`-Zlints` to enable this feature.
-[CHECKING] [..]
-[FINISHED] [..]
-",
- )
- .run();
-}
-
-#[cargo_test]
-fn workspace_requires_option() {
- let foo = project()
- .file(
- "Cargo.toml",
- r#"
- [package]
- name = "foo"
- version = "0.0.1"
- authors = []
-
- [workspace.lints.rust]
- unsafe_code = "forbid"
- "#,
- )
- .file("src/lib.rs", "")
- .build();
-
- foo.cargo("check")
- .with_stderr(
- "\
-warning: [CWD]/Cargo.toml: unused manifest key `lints` (may be supported in a future version)
-
-this Cargo does not support nightly features, but if you
-switch to nightly channel you can pass
-`-Zlints` to enable this feature.
-[CHECKING] [..]
-[FINISHED] [..]
-",
- )
- .run();
-}
-
-#[cargo_test]
fn dependency_warning_ignored() {
let foo = project()
.file(
@@ -133,53 +67,55 @@ fn malformed_on_stable() {
.build();
foo.cargo("check")
+ .with_status(101)
.with_stderr(
"\
-warning: unused manifest key `lints` (may be supported in a future version)
+error: failed to parse manifest[..]
-this Cargo does not support nightly features, but if you
-switch to nightly channel you can pass
-`-Zlints` to enable this feature.
-[CHECKING] [..]
-[FINISHED] [..]
+Caused by:
+ TOML parse error at line 2, column 25
+ |
+ 2 | lints = 20
+ | ^^
+ invalid type: integer `20`, expected a lints table
",
)
.run();
}
#[cargo_test]
-fn malformed_on_nightly() {
+fn fail_on_invalid_tool() {
let foo = project()
.file(
"Cargo.toml",
r#"
- lints = 20
[package]
name = "foo"
version = "0.0.1"
authors = []
+ [workspace.lints.super-awesome-linter]
+ unsafe_code = "forbid"
"#,
)
.file("src/lib.rs", "")
.build();
- foo.cargo("check -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
+ foo.cargo("check")
.with_status(101)
.with_stderr(
"\
-error: failed to parse manifest[..]
+[..]
Caused by:
- invalid type: integer `20`, expected a map
+ unsupported `super-awesome-linter` in `[lints]`, must be one of rust, clippy, rustdoc
",
)
.run();
}
#[cargo_test]
-fn fail_on_invalid_tool() {
+fn invalid_type_in_lint_value() {
let foo = project()
.file(
"Cargo.toml",
@@ -187,24 +123,26 @@ fn fail_on_invalid_tool() {
[package]
name = "foo"
version = "0.0.1"
- authors = []
- [workspace.lints.super-awesome-linter]
- unsafe_code = "forbid"
+ [workspace.lints.rust]
+ rust-2018-idioms = -1
"#,
)
.file("src/lib.rs", "")
.build();
- foo.cargo("check -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
+ foo.cargo("check")
.with_status(101)
.with_stderr(
"\
-[..]
+error: failed to parse manifest at `[..]/Cargo.toml`
Caused by:
- unsupported `super-awesome-linter` in `[lints]`, must be one of rust, clippy, rustdoc
+ TOML parse error at line 7, column 36
+ |
+ 7 | rust-2018-idioms = -1
+ | ^^
+ invalid type: integer `-1`, expected a string or map
",
)
.run();
@@ -228,8 +166,7 @@ fn fail_on_tool_injection() {
.file("src/lib.rs", "")
.build();
- foo.cargo("check -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
+ foo.cargo("check")
.with_status(101)
.with_stderr(
"\
@@ -260,8 +197,7 @@ fn fail_on_redundant_tool() {
.file("src/lib.rs", "")
.build();
- foo.cargo("check -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
+ foo.cargo("check")
.with_status(101)
.with_stderr(
"\
@@ -292,8 +228,7 @@ fn fail_on_conflicting_tool() {
.file("src/lib.rs", "")
.build();
- foo.cargo("check -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
+ foo.cargo("check")
.with_status(101)
.with_stderr(
"\
@@ -331,8 +266,7 @@ pub fn foo(num: i32) -> u32 {
)
.build();
- foo.cargo("check -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
+ foo.cargo("check")
.with_status(101)
.with_stderr_contains(
"\
@@ -370,8 +304,7 @@ pub fn foo(num: i32) -> u32 {
)
.build();
- foo.cargo("check -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
+ foo.cargo("check")
.with_status(101)
.with_stderr_contains(
"\
@@ -382,6 +315,49 @@ error: usage of an `unsafe` block
}
#[cargo_test]
+fn workspace_and_package_lints() {
+ let foo = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [lints]
+ workspace = true
+ [lints.rust]
+ "unsafe_code" = "allow"
+
+ [workspace.lints.rust]
+ "unsafe_code" = "deny"
+ "#,
+ )
+ .file(
+ "src/lib.rs",
+ "
+pub fn foo(num: i32) -> u32 {
+ unsafe { std::mem::transmute(num) }
+}
+",
+ )
+ .build();
+
+ foo.cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
+
+Caused by:
+ cannot override `workspace.lints` in `lints`, either remove the overrides or `lints.workspace = true` and manually specify the lints
+",
+ )
+ .run();
+}
+
+#[cargo_test]
fn attribute_has_precedence() {
let foo = project()
.file(
@@ -408,9 +384,8 @@ pub fn foo(num: i32) -> u32 {
)
.build();
- foo.cargo("check -Zlints")
+ foo.cargo("check")
.arg("-v") // Show order of rustflags on failure
- .masquerade_as_nightly_cargo(&["lints"])
.run();
}
@@ -439,10 +414,9 @@ pub fn foo(num: i32) -> u32 {
)
.build();
- foo.cargo("check -Zlints")
+ foo.cargo("check")
.arg("-v") // Show order of rustflags on failure
.env("RUSTFLAGS", "-Aunsafe_code")
- .masquerade_as_nightly_cargo(&["lints"])
.run();
}
@@ -475,9 +449,9 @@ pub fn foo(num: i32) -> u32 {
)
.build();
- foo.cargo("check -Zlints")
+ foo.cargo("check")
.arg("-v") // Show order of rustflags on failure
- .masquerade_as_nightly_cargo(&["lints", "profile-rustflags"])
+ .masquerade_as_nightly_cargo(&["profile-rustflags"])
.run();
}
@@ -512,9 +486,8 @@ pub fn foo(num: i32) -> u32 {
)
.build();
- foo.cargo("check -Zlints")
+ foo.cargo("check")
.arg("-v") // Show order of rustflags on failure
- .masquerade_as_nightly_cargo(&["lints"])
.run();
}
@@ -552,8 +525,7 @@ pub fn foo() -> u32 {
)
.build();
- foo.cargo("check -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
+ foo.cargo("check")
.with_status(101)
.with_stderr_contains(
"\
@@ -597,9 +569,7 @@ pub fn foo() -> u32 {
)
.build();
- foo.cargo("check -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
- .run();
+ foo.cargo("check").run();
}
#[cargo_test]
@@ -627,8 +597,7 @@ pub fn foo() -> u32 {
)
.build();
- foo.cargo("doc -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
+ foo.cargo("doc")
.with_status(101)
.with_stderr_contains(
"\
@@ -671,8 +640,7 @@ pub const Ä”: i32 = 2;
)
.build();
- foo.cargo("check -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
+ foo.cargo("check")
.with_stderr(
"\
[CHECKING] foo v0.0.1 ([CWD])
@@ -681,8 +649,7 @@ pub const Ä”: i32 = 2;
)
.run();
- foo.cargo("test --doc -Zlints")
- .masquerade_as_nightly_cargo(&["lints"])
+ foo.cargo("test --doc")
.with_stderr(
"\
[COMPILING] foo v0.0.1 ([CWD])
diff --git a/src/tools/cargo/tests/testsuite/list_availables.rs b/src/tools/cargo/tests/testsuite/list_availables.rs
index 6bbbeb160..fe635a19b 100644
--- a/src/tools/cargo/tests/testsuite/list_availables.rs
+++ b/src/tools/cargo/tests/testsuite/list_availables.rs
@@ -8,6 +8,7 @@ const BIN: u8 = 1 << 1;
const TEST: u8 = 1 << 2;
const BENCH: u8 = 1 << 3;
const PACKAGE: u8 = 1 << 4;
+const TARGET: u8 = 1 << 5;
fn list_availables_test(command: &str, targets: u8) {
let full_project = project()
@@ -159,56 +160,70 @@ No tests available.
.with_status(101)
.run();
}
+
+ if targets & TARGET != 0 {
+ empty_project
+ .cargo(&format!("{} --target", command))
+ .with_stderr(
+ "\
+error: \"--target\" takes a target architecture as an argument.
+
+Run `[..]` to see possible targets.
+",
+ )
+ .with_status(101)
+ .run();
+ }
}
#[cargo_test]
fn build_list_availables() {
- list_availables_test("build", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
+ list_availables_test("build", EXAMPLE | BIN | TEST | BENCH | PACKAGE | TARGET);
}
#[cargo_test]
fn check_list_availables() {
- list_availables_test("check", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
+ list_availables_test("check", EXAMPLE | BIN | TEST | BENCH | PACKAGE | TARGET);
}
#[cargo_test]
fn doc_list_availables() {
- list_availables_test("doc", BIN | PACKAGE);
+ list_availables_test("doc", BIN | PACKAGE | TARGET);
}
#[cargo_test]
fn fix_list_availables() {
- list_availables_test("fix", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
+ list_availables_test("fix", EXAMPLE | BIN | TEST | BENCH | PACKAGE | TARGET);
}
#[cargo_test]
fn run_list_availables() {
- list_availables_test("run", EXAMPLE | BIN | PACKAGE);
+ list_availables_test("run", EXAMPLE | BIN | PACKAGE | TARGET);
}
#[cargo_test]
fn test_list_availables() {
- list_availables_test("test", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
+ list_availables_test("test", EXAMPLE | BIN | TEST | BENCH | PACKAGE | TARGET);
}
#[cargo_test]
fn bench_list_availables() {
- list_availables_test("bench", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
+ list_availables_test("bench", EXAMPLE | BIN | TEST | BENCH | PACKAGE | TARGET);
}
#[cargo_test]
fn install_list_availables() {
- list_availables_test("install", EXAMPLE | BIN);
+ list_availables_test("install", EXAMPLE | BIN | TARGET);
}
#[cargo_test]
fn rustdoc_list_availables() {
- list_availables_test("rustdoc", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
+ list_availables_test("rustdoc", EXAMPLE | BIN | TEST | BENCH | PACKAGE | TARGET);
}
#[cargo_test]
fn rustc_list_availables() {
- list_availables_test("rustc", EXAMPLE | BIN | TEST | BENCH | PACKAGE);
+ list_availables_test("rustc", EXAMPLE | BIN | TEST | BENCH | PACKAGE | TARGET);
}
#[cargo_test]
@@ -218,12 +233,12 @@ fn pkgid_list_availables() {
#[cargo_test]
fn tree_list_availables() {
- list_availables_test("tree", PACKAGE);
+ list_availables_test("tree", PACKAGE | TARGET);
}
#[cargo_test]
fn clean_list_availables() {
- list_availables_test("clean", PACKAGE);
+ list_availables_test("clean", PACKAGE | TARGET);
}
#[cargo_test]
diff --git a/src/tools/cargo/tests/testsuite/login.rs b/src/tools/cargo/tests/testsuite/login.rs
index 16bd29dce..0eec734ce 100644
--- a/src/tools/cargo/tests/testsuite/login.rs
+++ b/src/tools/cargo/tests/testsuite/login.rs
@@ -197,8 +197,8 @@ fn bad_asymmetric_token_args() {
.build();
// These cases are kept brief as the implementation is covered by clap, so this is only smoke testing that we have clap configured correctly.
- cargo_process("login -Zcredential-process -- --key-subject")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ cargo_process("login -Zasymmetric-token -- --key-subject")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
.replace_crates_io(registry.index_url())
.with_stderr_contains(
" error: a value is required for '--key-subject <SUBJECT>' but none was supplied",
@@ -228,8 +228,8 @@ fn login_with_asymmetric_token_and_subject_on_stdin() {
.no_configure_token()
.build();
let credentials = credentials_toml();
- cargo_process("login -v -Z credential-process -- --key-subject=foo")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ cargo_process("login -v -Z asymmetric-token -- --key-subject=foo")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
.replace_crates_io(registry.index_url())
.with_stderr_contains(
"\
@@ -286,8 +286,8 @@ fn login_with_asymmetric_token_on_stdin() {
.no_configure_token()
.build();
let credentials = credentials_toml();
- cargo_process("login -vZ credential-process --registry alternative")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ cargo_process("login -v -Z asymmetric-token --registry alternative")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
.with_stderr(
"\
[UPDATING] [..]
@@ -308,8 +308,8 @@ fn login_with_generate_asymmetric_token() {
.no_configure_token()
.build();
let credentials = credentials_toml();
- cargo_process("login -Z credential-process --registry alternative")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ cargo_process("login -Z asymmetric-token --registry alternative")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
.with_stderr("[UPDATING] `alternative` index\nk3.public.[..]")
.run();
let credentials = fs::read_to_string(&credentials).unwrap();
diff --git a/src/tools/cargo/tests/testsuite/logout.rs b/src/tools/cargo/tests/testsuite/logout.rs
index 7b5e10de2..6829cec2a 100644
--- a/src/tools/cargo/tests/testsuite/logout.rs
+++ b/src/tools/cargo/tests/testsuite/logout.rs
@@ -83,8 +83,7 @@ fn default_registry_configured() {
check_token(Some("dummy-token"), Some("dummy-registry"));
check_token(Some("crates-io-token"), None);
- cargo_process("logout -Zunstable-options")
- .masquerade_as_nightly_cargo(&["cargo-logout"])
+ cargo_process("logout")
.with_stderr(
"\
[LOGOUT] token for `dummy-registry` has been removed from local storage
@@ -97,8 +96,24 @@ fn default_registry_configured() {
check_token(None, Some("dummy-registry"));
check_token(Some("crates-io-token"), None);
- cargo_process("logout -Zunstable-options")
- .masquerade_as_nightly_cargo(&["cargo-logout"])
+ cargo_process("logout")
.with_stderr("[LOGOUT] not currently logged in to `dummy-registry`")
.run();
}
+
+#[cargo_test]
+fn logout_asymmetric() {
+ let _registry = registry::RegistryBuilder::new()
+ .token(cargo_test_support::registry::Token::rfc_key())
+ .build();
+
+ cargo_process("logout --registry crates-io -Zasymmetric-token")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
+ .with_stderr("[LOGOUT] secret-key for `crates-io` has been removed from local storage")
+ .run();
+
+ cargo_process("logout --registry crates-io -Zasymmetric-token")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
+ .with_stderr("[LOGOUT] not currently logged in to `crates-io`")
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/lto.rs b/src/tools/cargo/tests/testsuite/lto.rs
index 40b4f7ca2..b4972a64d 100644
--- a/src/tools/cargo/tests/testsuite/lto.rs
+++ b/src/tools/cargo/tests/testsuite/lto.rs
@@ -453,10 +453,8 @@ fn verify_lto(output: &Output, krate: &str, krate_info: &str, expected_lto: Lto)
krate, krate_info, line, line2, stderr
);
}
- let actual_lto = if let Some(index) = line.find("-C lto=") {
- let s = &line[index..];
- let end = s.find(' ').unwrap();
- let mode = &line[index..index + end];
+ let actual_lto = if let Some((_, line)) = line.split_once("-C lto=") {
+ let mode = line.splitn(2, ' ').next().unwrap();
if mode == "off" {
Lto::Off
} else {
diff --git a/src/tools/cargo/tests/testsuite/metadata.rs b/src/tools/cargo/tests/testsuite/metadata.rs
index ac2cec396..fbead4dea 100644
--- a/src/tools/cargo/tests/testsuite/metadata.rs
+++ b/src/tools/cargo/tests/testsuite/metadata.rs
@@ -1821,8 +1821,11 @@ fn cargo_metadata_with_invalid_authors_field() {
r#"[ERROR] failed to parse manifest at `[..]`
Caused by:
- invalid type: string "", expected a vector of strings or workspace
- in `package.authors`"#,
+ TOML parse error at line 3, column 27
+ |
+ 3 | authors = ""
+ | ^^
+ invalid type: string "", expected a vector of strings or workspace"#,
)
.run();
}
@@ -1846,8 +1849,11 @@ fn cargo_metadata_with_invalid_version_field() {
r#"[ERROR] failed to parse manifest at `[..]`
Caused by:
- invalid type: integer `1`, expected SemVer version
- in `package.version`"#,
+ TOML parse error at line 3, column 27
+ |
+ 3 | version = 1
+ | ^
+ invalid type: integer `1`, expected SemVer version"#,
)
.run();
}
@@ -1871,8 +1877,11 @@ fn cargo_metadata_with_invalid_publish_field() {
r#"[ERROR] failed to parse manifest at `[..]`
Caused by:
- invalid type: string "foo", expected a boolean, a vector of strings, or workspace
- in `package.publish`"#,
+ TOML parse error at line 3, column 27
+ |
+ 3 | publish = "foo"
+ | ^^^^^
+ invalid type: string "foo", expected a boolean, a vector of strings, or workspace"#,
)
.run();
}
diff --git a/src/tools/cargo/tests/testsuite/new.rs b/src/tools/cargo/tests/testsuite/new.rs
index b9ddcf2d7..91a2871e9 100644
--- a/src/tools/cargo/tests/testsuite/new.rs
+++ b/src/tools/cargo/tests/testsuite/new.rs
@@ -95,7 +95,7 @@ fn simple_git() {
let fp = paths::root().join("foo/.gitignore");
let contents = fs::read_to_string(&fp).unwrap();
- assert_eq!(contents, "/target\n/Cargo.lock\n",);
+ assert_eq!(contents, "/target\n",);
cargo_process("build").cwd(&paths::root().join("foo")).run();
}
@@ -112,7 +112,7 @@ fn simple_hg() {
let fp = paths::root().join("foo/.hgignore");
let contents = fs::read_to_string(&fp).unwrap();
- assert_eq!(contents, "^target$\n^Cargo.lock$\n",);
+ assert_eq!(contents, "^target$\n",);
cargo_process("build").cwd(&paths::root().join("foo")).run();
}
diff --git a/src/tools/cargo/tests/testsuite/offline.rs b/src/tools/cargo/tests/testsuite/offline.rs
index 5f164dbeb..e68425319 100644
--- a/src/tools/cargo/tests/testsuite/offline.rs
+++ b/src/tools/cargo/tests/testsuite/offline.rs
@@ -673,7 +673,7 @@ fn main(){
.with_stdout("1.2.9")
.run();
// updates happen without updating the index
- p2.cargo("update -p present_dep --precise 1.2.3 --offline")
+ p2.cargo("update present_dep --precise 1.2.3 --offline")
.with_status(0)
.with_stderr(
"\
@@ -706,7 +706,7 @@ fn main(){
.run();
// No v1.2.8 loaded into the cache so expect failure.
- p2.cargo("update -p present_dep --precise 1.2.8 --offline")
+ p2.cargo("update present_dep --precise 1.2.8 --offline")
.with_status(101)
.with_stderr(
"\
diff --git a/src/tools/cargo/tests/testsuite/owner.rs b/src/tools/cargo/tests/testsuite/owner.rs
index 7b38bcc5e..fc0e0b5c4 100644
--- a/src/tools/cargo/tests/testsuite/owner.rs
+++ b/src/tools/cargo/tests/testsuite/owner.rs
@@ -117,8 +117,8 @@ fn simple_add_with_asymmetric() {
// The http_api server will check that the authorization is correct.
// If the authorization was not sent then we would get an unauthorized error.
p.cargo("owner -a username")
- .arg("-Zcredential-process")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ .arg("-Zasymmetric-token")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
.replace_crates_io(registry.index_url())
.with_status(0)
.run();
@@ -184,9 +184,9 @@ fn simple_remove_with_asymmetric() {
// The http_api server will check that the authorization is correct.
// If the authorization was not sent then we would get an unauthorized error.
p.cargo("owner -r username")
- .arg("-Zcredential-process")
+ .arg("-Zasymmetric-token")
.replace_crates_io(registry.index_url())
- .masquerade_as_nightly_cargo(&["credential-process"])
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
.with_status(0)
.run();
}
diff --git a/src/tools/cargo/tests/testsuite/patch.rs b/src/tools/cargo/tests/testsuite/patch.rs
index f2f077d7d..a467f60b5 100644
--- a/src/tools/cargo/tests/testsuite/patch.rs
+++ b/src/tools/cargo/tests/testsuite/patch.rs
@@ -1965,8 +1965,8 @@ fn update_unused_new_version() {
// Restore the lock file, and see if `update` will work, too.
fs::copy(p.root().join("Cargo.lock.bak"), p.root().join("Cargo.lock")).unwrap();
- // Try `update -p`.
- p.cargo("update -p bar")
+ // Try `update <pkg>`.
+ p.cargo("update bar")
.with_stderr(
"\
[UPDATING] `dummy-registry` index
@@ -2425,7 +2425,7 @@ fn can_update_with_alt_reg() {
p.cargo("check").with_stderr("[FINISHED] [..]").run();
// This does nothing, due to `=` requirement.
- p.cargo("update -p bar")
+ p.cargo("update bar")
.with_stderr(
"\
[UPDATING] `alternative` index
@@ -2658,3 +2658,45 @@ failed to select a version for `qux` which could resolve this conflict"#,
)
.run();
}
+
+#[cargo_test]
+fn mismatched_version_with_prerelease() {
+ Package::new("prerelease-deps", "0.0.1").publish();
+ // A patch to a location that has an prerelease version
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ prerelease-deps = "0.1.0"
+
+ [patch.crates-io]
+ prerelease-deps = { path = "./prerelease-deps" }
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file(
+ "prerelease-deps/Cargo.toml",
+ &basic_manifest("prerelease-deps", "0.1.1-pre1"),
+ )
+ .file("prerelease-deps/src/lib.rs", "")
+ .build();
+
+ p.cargo("generate-lockfile")
+ .with_status(101)
+ .with_stderr(
+ r#"[UPDATING] `dummy-registry` index
+[ERROR] failed to select a version for the requirement `prerelease-deps = "^0.1.0"`
+candidate versions found which didn't match: 0.1.1-pre1, 0.0.1
+location searched: `dummy-registry` index (which is replacing registry `crates-io`)
+required by package `foo v0.1.0 [..]`
+if you are looking for the prerelease package it needs to be specified explicitly
+ prerelease-deps = { version = "0.1.1-pre1" }
+perhaps a crate was updated and forgotten to be re-vendored?"#,
+ )
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/pkgid.rs b/src/tools/cargo/tests/testsuite/pkgid.rs
index 3e3e4692a..88d991e80 100644
--- a/src/tools/cargo/tests/testsuite/pkgid.rs
+++ b/src/tools/cargo/tests/testsuite/pkgid.rs
@@ -4,22 +4,31 @@ use cargo_test_support::project;
use cargo_test_support::registry::Package;
#[cargo_test]
-fn simple() {
- Package::new("bar", "0.1.0").publish();
+fn local() {
let p = project()
.file(
"Cargo.toml",
r#"
+ [workspace]
+ members = ["bar"]
+
[package]
name = "foo"
version = "0.1.0"
edition = "2018"
-
- [dependencies]
- bar = "0.1.0"
"#,
)
.file("src/main.rs", "fn main() {}")
+ .file(
+ "bar/Cargo.toml",
+ r#"
+ [package]
+ name = "bar"
+ version = "0.1.0"
+ edition = "2018"
+ "#,
+ )
+ .file("bar/src/main.rs", "fn main() {}")
.build();
p.cargo("generate-lockfile").run();
@@ -28,16 +37,38 @@ fn simple() {
.with_stdout(format!("file://[..]{}#0.1.0", p.root().to_str().unwrap()))
.run();
- p.cargo("pkgid bar")
- .with_stdout("https://github.com/rust-lang/crates.io-index#bar@0.1.0")
+ // Bad file URL.
+ p.cargo("pkgid ./Cargo.toml")
+ .with_status(101)
+ .with_stderr(
+ "\
+error: invalid package ID specification: `./Cargo.toml`
+
+Caused by:
+ package ID specification `./Cargo.toml` looks like a file path, maybe try file://[..]/Cargo.toml
+",
+ )
+ .run();
+
+ // Bad file URL with similar name.
+ p.cargo("pkgid './bar'")
+ .with_status(101)
+ .with_stderr(
+ "\
+error: invalid package ID specification: `./bar`
+
+<tab>Did you mean `bar`?
+
+Caused by:
+ package ID specification `./bar` looks like a file path, maybe try file://[..]/bar
+",
+ )
.run();
}
#[cargo_test]
-fn suggestion_bad_pkgid() {
+fn registry() {
Package::new("crates-io", "0.1.0").publish();
- Package::new("two-ver", "0.1.0").publish();
- Package::new("two-ver", "0.2.0").publish();
let p = project()
.file(
"Cargo.toml",
@@ -49,16 +80,18 @@ fn suggestion_bad_pkgid() {
[dependencies]
crates-io = "0.1.0"
- two-ver = "0.1.0"
- two-ver2 = { package = "two-ver", version = "0.2.0" }
"#,
)
- .file("src/lib.rs", "")
+ .file("src/main.rs", "fn main() {}")
.file("cratesio", "")
.build();
p.cargo("generate-lockfile").run();
+ p.cargo("pkgid crates-io")
+ .with_stdout("https://github.com/rust-lang/crates.io-index#crates-io@0.1.0")
+ .run();
+
// Bad URL.
p.cargo("pkgid https://example.com/crates-io")
.with_status(101)
@@ -83,45 +116,81 @@ error: package ID specification `crates_io` did not match any packages
",
)
.run();
+}
- // Bad version.
- p.cargo("pkgid two-ver:0.3.0")
+#[cargo_test]
+fn multiple_versions() {
+ Package::new("two-ver", "0.1.0").publish();
+ Package::new("two-ver", "0.2.0").publish();
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ edition = "2018"
+
+ [dependencies]
+ two-ver = "0.1.0"
+ two-ver2 = { package = "two-ver", version = "0.2.0" }
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("cratesio", "")
+ .build();
+
+ p.cargo("generate-lockfile").run();
+
+ p.cargo("pkgid two-ver:0.2.0")
+ .with_stdout("https://github.com/rust-lang/crates.io-index#two-ver@0.2.0")
+ .run();
+
+ // Incomplete version.
+ p.cargo("pkgid two-ver@0")
.with_status(101)
.with_stderr(
"\
-error: package ID specification `two-ver@0.3.0` did not match any packages
-Did you mean one of these?
-
+error: There are multiple `two-ver` packages in your project, and the specification `two-ver@0` is ambiguous.
+Please re-run this command with one of the following specifications:
two-ver@0.1.0
two-ver@0.2.0
",
)
.run();
- // Bad file URL.
- p.cargo("pkgid ./Cargo.toml")
+ // Incomplete version.
+ p.cargo("pkgid two-ver@0.2")
+ .with_stdout(
+ "\
+https://github.com/rust-lang/crates.io-index#two-ver@0.2.0
+",
+ )
+ .run();
+
+ // Ambiguous.
+ p.cargo("pkgid two-ver")
.with_status(101)
.with_stderr(
"\
-error: invalid package ID specification: `./Cargo.toml`
-
-Caused by:
- package ID specification `./Cargo.toml` looks like a file path, maybe try file://[..]/Cargo.toml
+error: There are multiple `two-ver` packages in your project, and the specification `two-ver` is ambiguous.
+Please re-run this command with one of the following specifications:
+ two-ver@0.1.0
+ two-ver@0.2.0
",
)
.run();
- // Bad file URL with similar name.
- p.cargo("pkgid './cratesio'")
+ // Bad version.
+ p.cargo("pkgid two-ver:0.3.0")
.with_status(101)
.with_stderr(
"\
-error: invalid package ID specification: `./cratesio`
-
-<tab>Did you mean `crates-io`?
+error: package ID specification `two-ver@0.3.0` did not match any packages
+Did you mean one of these?
-Caused by:
- package ID specification `./cratesio` looks like a file path, maybe try file://[..]/cratesio
+ two-ver@0.1.0
+ two-ver@0.2.0
",
)
.run();
diff --git a/src/tools/cargo/tests/testsuite/profile_config.rs b/src/tools/cargo/tests/testsuite/profile_config.rs
index 26104e7e7..143c050f9 100644
--- a/src/tools/cargo/tests/testsuite/profile_config.rs
+++ b/src/tools/cargo/tests/testsuite/profile_config.rs
@@ -370,7 +370,7 @@ fn profile_config_mixed_types() {
#[cargo_test]
fn named_config_profile() {
- // Exercises config named profies.
+ // Exercises config named profiles.
// foo -> middle -> bar -> dev
// middle exists in Cargo.toml, the others in .cargo/config
use super::config::ConfigBuilder;
@@ -427,7 +427,7 @@ fn named_config_profile() {
let ws = Workspace::new(&paths::root().join("Cargo.toml"), &config).unwrap();
let profiles = Profiles::new(&ws, profile_name).unwrap();
- let crates_io = cargo::core::source::SourceId::crates_io(&config).unwrap();
+ let crates_io = cargo::core::SourceId::crates_io(&config).unwrap();
let a_pkg = PackageId::new("a", "0.1.0", crates_io).unwrap();
let dep_pkg = PackageId::new("dep", "0.1.0", crates_io).unwrap();
diff --git a/src/tools/cargo/tests/testsuite/profile_custom.rs b/src/tools/cargo/tests/testsuite/profile_custom.rs
index ea6b54c95..f7139e552 100644
--- a/src/tools/cargo/tests/testsuite/profile_custom.rs
+++ b/src/tools/cargo/tests/testsuite/profile_custom.rs
@@ -543,7 +543,9 @@ fn clean_custom_dirname() {
assert!(!p.build_dir().join("release").is_dir());
// This should clean 'other'
- p.cargo("clean --profile=other").with_stderr("").run();
+ p.cargo("clean --profile=other")
+ .with_stderr("[REMOVED] [..] files, [..] total")
+ .run();
assert!(p.build_dir().join("debug").is_dir());
assert!(!p.build_dir().join("other").is_dir());
}
diff --git a/src/tools/cargo/tests/testsuite/profile_overrides.rs b/src/tools/cargo/tests/testsuite/profile_overrides.rs
index dc9bafba1..65d9f3b51 100644
--- a/src/tools/cargo/tests/testsuite/profile_overrides.rs
+++ b/src/tools/cargo/tests/testsuite/profile_overrides.rs
@@ -268,6 +268,60 @@ found package specs: bar, bar@0.5.0",
}
#[cargo_test]
+fn profile_override_spec_with_version() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [profile.dev.package."bar:0.5.0"]
+ codegen-units = 2
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ p.cargo("check -v")
+ .with_stderr_contains("[RUNNING] `rustc [..]bar/src/lib.rs [..] -C codegen-units=2 [..]")
+ .run();
+}
+
+#[cargo_test]
+fn profile_override_spec_with_partial_version() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+
+ [dependencies]
+ bar = { path = "bar" }
+
+ [profile.dev.package."bar:0.5"]
+ codegen-units = 2
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
+ .file("bar/src/lib.rs", "")
+ .build();
+
+ p.cargo("check -v")
+ .with_stderr_contains("[RUNNING] `rustc [..]bar/src/lib.rs [..] -C codegen-units=2 [..]")
+ .run();
+}
+
+#[cargo_test]
fn profile_override_spec() {
let p = project()
.file(
diff --git a/src/tools/cargo/tests/testsuite/profiles.rs b/src/tools/cargo/tests/testsuite/profiles.rs
index 465ab3b99..531c02700 100644
--- a/src/tools/cargo/tests/testsuite/profiles.rs
+++ b/src/tools/cargo/tests/testsuite/profiles.rs
@@ -744,7 +744,7 @@ Caused by:
.run();
}
-#[cargo_test(nightly, reason = "debug options stabilized in 1.70")]
+#[cargo_test]
fn debug_options_valid() {
let build = |option| {
let p = project()
diff --git a/src/tools/cargo/tests/testsuite/publish.rs b/src/tools/cargo/tests/testsuite/publish.rs
index 50ad697d5..67569bf3b 100644
--- a/src/tools/cargo/tests/testsuite/publish.rs
+++ b/src/tools/cargo/tests/testsuite/publish.rs
@@ -194,8 +194,8 @@ fn simple_publish_with_asymmetric() {
.file("src/main.rs", "fn main() {}")
.build();
- p.cargo("publish --no-verify -Zcredential-process --registry dummy-registry")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ p.cargo("publish --no-verify -Zasymmetric-token --registry dummy-registry")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
.with_stderr(
"\
[UPDATING] `dummy-registry` index
@@ -922,6 +922,48 @@ You may press ctrl-c [..]
}
#[cargo_test]
+fn publish_failed_with_index_and_only_allowed_registry() {
+ let registry = RegistryBuilder::new()
+ .http_api()
+ .http_index()
+ .alternative()
+ .build();
+
+ let p = project().build();
+
+ let _ = repo(&paths::root().join("foo"))
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ license = "MIT"
+ description = "foo"
+ documentation = "foo"
+ homepage = "foo"
+ repository = "foo"
+ publish = ["alternative"]
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .build();
+
+ p.cargo("publish")
+ .arg("--index")
+ .arg(registry.index_url().as_str())
+ .with_status(101)
+ .with_stderr(
+ "\
+[NOTE] Found `alternative` as only allowed registry. Publishing to it automatically.
+[ERROR] command-line argument --index requires --token to be specified
+",
+ )
+ .run();
+}
+
+#[cargo_test]
fn publish_fail_with_no_registry_specified() {
let p = project().build();
@@ -1923,6 +1965,7 @@ Caused by:
headers:
<tab>HTTP/1.1 400
<tab>Content-Length: 7
+ <tab>Connection: close
<tab>
body:
go away
diff --git a/src/tools/cargo/tests/testsuite/registry.rs b/src/tools/cargo/tests/testsuite/registry.rs
index 8982b1cb6..f485180c9 100644
--- a/src/tools/cargo/tests/testsuite/registry.rs
+++ b/src/tools/cargo/tests/testsuite/registry.rs
@@ -807,7 +807,7 @@ required by package `foo v0.0.1 ([..])`
)
.run();
- p.cargo("update -p baz")
+ p.cargo("update baz")
.with_stderr_contains(
"\
[UPDATING] `[..]` index
@@ -952,7 +952,7 @@ fn update_lockfile() {
Package::new("bar", "0.0.3").publish();
paths::home().join(".cargo/registry").rm_rf();
println!("0.0.2 update");
- p.cargo("update -p bar --precise 0.0.2")
+ p.cargo("update bar --precise 0.0.2")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -975,7 +975,7 @@ fn update_lockfile() {
.run();
println!("0.0.3 update");
- p.cargo("update -p bar")
+ p.cargo("update bar")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -1000,7 +1000,7 @@ fn update_lockfile() {
println!("new dependencies update");
Package::new("bar", "0.0.4").dep("spam", "0.2.5").publish();
Package::new("spam", "0.2.5").publish();
- p.cargo("update -p bar")
+ p.cargo("update bar")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -1012,7 +1012,7 @@ fn update_lockfile() {
println!("new dependencies update");
Package::new("bar", "0.0.5").publish();
- p.cargo("update -p bar")
+ p.cargo("update bar")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -1433,7 +1433,7 @@ fn update_transitive_dependency() {
Package::new("b", "0.1.1").publish();
- p.cargo("update -pb")
+ p.cargo("update b")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -1504,7 +1504,7 @@ fn update_backtracking_ok() {
.dep("cookie", "0.1.0")
.publish();
- p.cargo("update -p hyper")
+ p.cargo("update hyper")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -1555,7 +1555,7 @@ fn update_multiple_packages() {
Package::new("b", "0.1.1").publish();
Package::new("c", "0.1.1").publish();
- p.cargo("update -pa -pb")
+ p.cargo("update a b")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -1565,7 +1565,7 @@ fn update_multiple_packages() {
)
.run();
- p.cargo("update -pb -pc")
+ p.cargo("update b c")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -1671,7 +1671,7 @@ fn update_same_prefix_oh_my_how_was_this_a_bug() {
.publish();
p.cargo("generate-lockfile").run();
- p.cargo("update -pfoobar --precise=0.2.0").run();
+ p.cargo("update foobar --precise=0.2.0").run();
}
#[cargo_test]
@@ -1756,12 +1756,12 @@ fn use_semver_package_incorrectly() {
.with_status(101)
.with_stderr(
"\
-error: no matching package found
-searched package name: `a`
-prerelease package needs to be specified explicitly
-a = { version = \"0.1.1-alpha.0\" }
+error: failed to select a version for the requirement `a = \"^0.1\"`
+candidate versions found which didn't match: 0.1.1-alpha.0
location searched: [..]
required by package `b v0.1.0 ([..])`
+if you are looking for the prerelease package it needs to be specified explicitly
+ a = { version = \"0.1.1-alpha.0\" }
",
)
.run();
@@ -2604,7 +2604,9 @@ fn ignores_unknown_index_version_git() {
fn ignores_unknown_index_version() {
// If the version field is not understood, it is ignored.
Package::new("bar", "1.0.0").publish();
- Package::new("bar", "1.0.1").schema_version(9999).publish();
+ Package::new("bar", "1.0.1")
+ .schema_version(u32::MAX)
+ .publish();
let p = project()
.file(
@@ -2631,6 +2633,41 @@ fn ignores_unknown_index_version() {
}
#[cargo_test]
+fn unknown_index_version_error() {
+ // If the version field is not understood, it is ignored.
+ Package::new("bar", "1.0.1")
+ .schema_version(u32::MAX)
+ .publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+
+ [dependencies]
+ bar = "1.0"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("generate-lockfile")
+ .with_status(101)
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[ERROR] no matching package named `bar` found
+location searched: registry `crates-io`
+required by package `foo v0.1.0 ([CWD])`
+",
+ )
+ .run();
+}
+
+#[cargo_test]
fn protocol() {
cargo_process("install bar")
.with_status(101)
diff --git a/src/tools/cargo/tests/testsuite/registry_auth.rs b/src/tools/cargo/tests/testsuite/registry_auth.rs
index 4422c638a..df2bdf565 100644
--- a/src/tools/cargo/tests/testsuite/registry_auth.rs
+++ b/src/tools/cargo/tests/testsuite/registry_auth.rs
@@ -6,9 +6,12 @@ use cargo_test_support::{project, Execs, Project};
fn cargo(p: &Project, s: &str) -> Execs {
let mut e = p.cargo(s);
- e.masquerade_as_nightly_cargo(&["registry-auth", "credential-process"])
- .arg("-Zregistry-auth")
- .arg("-Zcredential-process");
+ e.masquerade_as_nightly_cargo(&["asymmetric-token"])
+ .arg("-Zasymmetric-token");
+ e.env(
+ "CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS",
+ "cargo:paseto cargo:token",
+ );
e
}
@@ -43,7 +46,7 @@ static SUCCESS_OUTPUT: &'static str = "\
";
#[cargo_test]
-fn requires_nightly() {
+fn requires_credential_provider() {
let _registry = RegistryBuilder::new()
.alternative()
.auth_required()
@@ -55,14 +58,14 @@ fn requires_nightly() {
.with_status(101)
.with_stderr(
r#"[UPDATING] `alternative` index
-[DOWNLOADING] crates ...
-error: failed to download from `[..]/dl/bar/0.0.1/download`
+error: failed to download `bar v0.0.1 (registry `alternative`)`
Caused by:
- failed to get successful HTTP response from `[..]` (127.0.0.1), got 401
- body:
- Unauthorized message from server.
-"#,
+ unable to get packages from source
+
+Caused by:
+ authenticated registries require a credential-provider to be configured
+ see https://doc.rust-lang.org/cargo/reference/registry-authentication.html for details"#,
)
.run();
}
diff --git a/src/tools/cargo/tests/testsuite/replace.rs b/src/tools/cargo/tests/testsuite/replace.rs
index c11c49330..b9de51d2f 100644
--- a/src/tools/cargo/tests/testsuite/replace.rs
+++ b/src/tools/cargo/tests/testsuite/replace.rs
@@ -533,7 +533,7 @@ fn override_adds_some_deps() {
p.cargo("check").with_stdout("").run();
Package::new("baz", "0.1.2").publish();
- p.cargo("update -p")
+ p.cargo("update")
.arg(&format!("{}#bar", foo.url()))
.with_stderr(
"\
@@ -542,7 +542,7 @@ fn override_adds_some_deps() {
",
)
.run();
- p.cargo("update -p https://github.com/rust-lang/crates.io-index#bar")
+ p.cargo("update https://github.com/rust-lang/crates.io-index#bar")
.with_stderr(
"\
[UPDATING] `dummy-registry` index
@@ -1298,3 +1298,157 @@ fn override_plus_dep() {
.with_stderr_contains("error: cyclic package dependency: [..]")
.run();
}
+
+#[cargo_test]
+fn override_generic_matching_other_versions() {
+ Package::new("bar", "0.1.0+a").publish();
+
+ let bar = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
+ .file("src/lib.rs", "pub fn bar() {}")
+ .build();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+
+ [replace]
+ "bar:0.1.0" = {{ git = '{}' }}
+ "#,
+ bar.url()
+ ),
+ )
+ .file(
+ "src/lib.rs",
+ "extern crate bar; pub fn foo() { bar::bar(); }",
+ )
+ .build();
+
+ p.cargo("check")
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[UPDATING] git repository `[..]`
+[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([..]/foo)`
+
+Caused by:
+ replacement specification `https://github.com/rust-lang/crates.io-index#bar@0.1.0` matched 0.1.0+a and tried to override it with 0.1.0
+ avoid matching unrelated packages by being more specific
+",
+ )
+ .with_status(101)
+ .run();
+}
+
+#[cargo_test]
+fn override_respects_spec_metadata() {
+ Package::new("bar", "0.1.0+a").publish();
+
+ let bar = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", &basic_manifest("bar", "0.1.0+a"))
+ .file("src/lib.rs", "pub fn bar() {}")
+ .build();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+
+ [replace]
+ "bar:0.1.0+notTheBuild" = {{ git = '{}' }}
+ "#,
+ bar.url()
+ ),
+ )
+ .file(
+ "src/lib.rs",
+ "extern crate bar; pub fn foo() { bar::bar(); }",
+ )
+ .build();
+
+ p.cargo("check")
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[WARNING] package replacement is not used: https://github.com/rust-lang/crates.io-index#bar@0.1.0+notTheBuild
+[DOWNLOADING] crates ...
+[DOWNLOADED] bar v0.1.0+a (registry `dummy-registry`)
+[CHECKING] bar v0.1.0+a
+[CHECKING] foo v0.0.1 ([..]/foo)
+[..]
+[..]
+[..]
+[..]
+[..]
+[..]
+[..]
+error: could not compile `foo` (lib) due to previous error
+",
+ )
+ .with_status(101)
+ .run();
+}
+
+#[cargo_test]
+fn override_spec_metadata_is_optional() {
+ Package::new("bar", "0.1.0+a").publish();
+
+ let bar = git::repo(&paths::root().join("override"))
+ .file("Cargo.toml", &basic_manifest("bar", "0.1.0+a"))
+ .file("src/lib.rs", "pub fn bar() {}")
+ .build();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ &format!(
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ bar = "0.1.0"
+
+ [replace]
+ "bar:0.1.0" = {{ git = '{}' }}
+ "#,
+ bar.url()
+ ),
+ )
+ .file(
+ "src/lib.rs",
+ "extern crate bar; pub fn foo() { bar::bar(); }",
+ )
+ .build();
+
+ p.cargo("check")
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[UPDATING] git repository `[..]`
+[CHECKING] bar v0.1.0+a (file://[..])
+[CHECKING] foo v0.0.1 ([CWD])
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/run.rs b/src/tools/cargo/tests/testsuite/run.rs
index 64cf4e16c..c58c239ac 100644
--- a/src/tools/cargo/tests/testsuite/run.rs
+++ b/src/tools/cargo/tests/testsuite/run.rs
@@ -38,6 +38,43 @@ fn quiet_arg() {
}
#[cargo_test]
+fn unsupported_silent_arg() {
+ let p = project()
+ .file("src/main.rs", r#"fn main() { println!("hello"); }"#)
+ .build();
+
+ p.cargo("run -s")
+ .with_stderr(
+ "\
+error: unexpected argument '--silent' found
+
+ tip: a similar argument exists: '--quiet'
+
+Usage: cargo[EXE] run [OPTIONS] [args]...
+
+For more information, try '--help'.
+",
+ )
+ .with_status(1)
+ .run();
+
+ p.cargo("run --silent")
+ .with_stderr(
+ "\
+error: unexpected argument '--silent' found
+
+ tip: a similar argument exists: '--quiet'
+
+Usage: cargo[EXE] run [OPTIONS] [args]...
+
+For more information, try '--help'.
+",
+ )
+ .with_status(1)
+ .run();
+}
+
+#[cargo_test]
fn quiet_arg_and_verbose_arg() {
let p = project()
.file("src/main.rs", r#"fn main() { println!("hello"); }"#)
diff --git a/src/tools/cargo/tests/testsuite/rust_version.rs b/src/tools/cargo/tests/testsuite/rust_version.rs
index 91711cf1a..21321b7c5 100644
--- a/src/tools/cargo/tests/testsuite/rust_version.rs
+++ b/src/tools/cargo/tests/testsuite/rust_version.rs
@@ -44,8 +44,48 @@ fn rust_version_bad_caret() {
.cargo("check")
.with_status(101)
.with_stderr(
- "error: failed to parse manifest at `[..]`\n\n\
- Caused by:\n `rust-version` must be a value like \"1.32\"",
+ "\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ TOML parse error at line 6, column 28
+ |
+ 6 | rust-version = \"^1.43\"
+ | ^^^^^^^
+ unexpected version requirement, expected a version like \"1.32\"",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn rust_version_good_pre_release() {
+ project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ rust-version = "1.43.0-beta.1"
+ [[bin]]
+ name = "foo"
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .build()
+ .cargo("check")
+ .with_status(101)
+ .with_stderr(
+ "\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ TOML parse error at line 6, column 28
+ |
+ 6 | rust-version = \"1.43.0-beta.1\"
+ | ^^^^^^^^^^^^^^^
+ unexpected prerelease field, expected a version like \"1.32\"",
)
.run();
}
@@ -70,8 +110,15 @@ fn rust_version_bad_pre_release() {
.cargo("check")
.with_status(101)
.with_stderr(
- "error: failed to parse manifest at `[..]`\n\n\
- Caused by:\n `rust-version` must be a value like \"1.32\"",
+ "\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ TOML parse error at line 6, column 28
+ |
+ 6 | rust-version = \"1.43-beta.1\"
+ | ^^^^^^^^^^^^^
+ unexpected prerelease field, expected a version like \"1.32\"",
)
.run();
}
@@ -96,8 +143,15 @@ fn rust_version_bad_nonsense() {
.cargo("check")
.with_status(101)
.with_stderr(
- "error: failed to parse manifest at `[..]`\n\n\
- Caused by:\n `rust-version` must be a value like \"1.32\"",
+ "\
+error: failed to parse manifest at `[..]`
+
+Caused by:
+ TOML parse error at line 6, column 28
+ |
+ 6 | rust-version = \"foodaddle\"
+ | ^^^^^^^^^^^
+ expected a version like \"1.32\"",
)
.run();
}
@@ -131,7 +185,7 @@ fn rust_version_too_high() {
}
#[cargo_test]
-fn rust_version_dependency_fails() {
+fn dependency_rust_version_newer_than_rustc() {
Package::new("bar", "0.0.1")
.rust_version("1.2345.0")
.file("src/lib.rs", "fn other_stuff() {}")
@@ -161,7 +215,7 @@ fn rust_version_dependency_fails() {
error: package `bar v0.0.1` cannot be built because it requires \
rustc 1.2345.0 or newer, while the currently active rustc version is [..]\n\
Either upgrade to rustc 1.2345.0 or newer, or use\n\
- cargo update -p bar@0.0.1 --precise ver\n\
+ cargo update bar@0.0.1 --precise ver\n\
where `ver` is the latest version of `bar` supporting rustc [..]",
)
.run();
@@ -169,6 +223,189 @@ fn rust_version_dependency_fails() {
}
#[cargo_test]
+fn dependency_rust_version_newer_than_package() {
+ Package::new("bar", "1.6.0")
+ .rust_version("1.65.0")
+ .file("src/lib.rs", "fn other_stuff() {}")
+ .publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ rust-version = "1.60.0"
+ [dependencies]
+ bar = "1.0.0"
+ "#,
+ )
+ .file("src/main.rs", "fn main(){}")
+ .build();
+
+ p.cargo("check --ignore-rust-version")
+ .arg("-Zmsrv-policy")
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ // This shouldn't fail
+ .with_status(101)
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[ERROR] failed to select a version for the requirement `bar = \"^1.0.0\"`
+candidate versions found which didn't match: 1.6.0
+location searched: `dummy-registry` index (which is replacing registry `crates-io`)
+required by package `foo v0.0.1 ([CWD])`
+perhaps a crate was updated and forgotten to be re-vendored?
+",
+ )
+ .run();
+ p.cargo("check")
+ .arg("-Zmsrv-policy")
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .with_status(101)
+ // This should have a better error message
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[ERROR] failed to select a version for the requirement `bar = \"^1.0.0\"`
+candidate versions found which didn't match: 1.6.0
+location searched: `dummy-registry` index (which is replacing registry `crates-io`)
+required by package `foo v0.0.1 ([CWD])`
+perhaps a crate was updated and forgotten to be re-vendored?
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn dependency_rust_version_older_and_newer_than_package() {
+ Package::new("bar", "1.5.0")
+ .rust_version("1.55.0")
+ .file("src/lib.rs", "fn other_stuff() {}")
+ .publish();
+ Package::new("bar", "1.6.0")
+ .rust_version("1.65.0")
+ .file("src/lib.rs", "fn other_stuff() {}")
+ .publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+ rust-version = "1.60.0"
+ [dependencies]
+ bar = "1.0.0"
+ "#,
+ )
+ .file("src/main.rs", "fn main(){}")
+ .build();
+
+ p.cargo("check --ignore-rust-version")
+ .arg("-Zmsrv-policy")
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ // This should pick 1.6.0
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] bar v1.5.0 (registry `dummy-registry`)
+[CHECKING] bar v1.5.0
+[CHECKING] [..]
+[FINISHED] [..]
+",
+ )
+ .run();
+ p.cargo("check")
+ .arg("-Zmsrv-policy")
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .with_stderr(
+ "\
+[FINISHED] [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn workspace_with_mixed_rust_version() {
+ Package::new("bar", "1.4.0")
+ .rust_version("1.45.0")
+ .file("src/lib.rs", "fn other_stuff() {}")
+ .publish();
+ Package::new("bar", "1.5.0")
+ .rust_version("1.55.0")
+ .file("src/lib.rs", "fn other_stuff() {}")
+ .publish();
+ Package::new("bar", "1.6.0")
+ .rust_version("1.65.0")
+ .file("src/lib.rs", "fn other_stuff() {}")
+ .publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [workspace]
+ members = ["lower"]
+
+ [package]
+ name = "higher"
+ version = "0.0.1"
+ authors = []
+ rust-version = "1.60.0"
+ [dependencies]
+ bar = "1.0.0"
+ "#,
+ )
+ .file("src/main.rs", "fn main() {}")
+ .file(
+ "lower/Cargo.toml",
+ r#"
+ [package]
+ name = "lower"
+ version = "0.0.1"
+ authors = []
+ rust-version = "1.50.0"
+ [dependencies]
+ bar = "1.0.0"
+ "#,
+ )
+ .file("lower/src/main.rs", "fn main() {}")
+ .build();
+
+ p.cargo("check --ignore-rust-version")
+ .arg("-Zmsrv-policy")
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ // This should pick 1.6.0
+ .with_stderr(
+ "\
+[UPDATING] `dummy-registry` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] bar v1.4.0 (registry `dummy-registry`)
+[CHECKING] bar v1.4.0
+[CHECKING] [..]
+[FINISHED] [..]
+",
+ )
+ .run();
+ p.cargo("check")
+ .arg("-Zmsrv-policy")
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .with_stderr(
+ "\
+[FINISHED] [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
fn rust_version_older_than_edition() {
project()
.file(
diff --git a/src/tools/cargo/tests/testsuite/rustdocflags.rs b/src/tools/cargo/tests/testsuite/rustdocflags.rs
index 6992961ce..c37d5a826 100644
--- a/src/tools/cargo/tests/testsuite/rustdocflags.rs
+++ b/src/tools/cargo/tests/testsuite/rustdocflags.rs
@@ -110,17 +110,19 @@ fn whitespace() {
.with_status(101)
.run();
- const SPACED_VERSION: &str = "a\nb\tc\u{00a0}d";
p.cargo("doc")
.env_remove("__CARGO_TEST_FORCE_ARGFILE") // Not applicable for argfile.
.env(
"RUSTDOCFLAGS",
- format!("--crate-version {}", SPACED_VERSION),
+ "--crate-version 1111\n2222\t3333\u{00a0}4444",
)
.run();
let contents = p.read_file("target/doc/foo/index.html");
- assert!(contents.contains(SPACED_VERSION));
+ assert!(contents.contains("1111"));
+ assert!(contents.contains("2222"));
+ assert!(contents.contains("3333"));
+ assert!(contents.contains("4444"));
}
#[cargo_test]
diff --git a/src/tools/cargo/tests/testsuite/script.rs b/src/tools/cargo/tests/testsuite/script.rs
index 0c0441d62..96f3a5eb4 100644
--- a/src/tools/cargo/tests/testsuite/script.rs
+++ b/src/tools/cargo/tests/testsuite/script.rs
@@ -162,7 +162,7 @@ fn warn_when_plugin_masks_manifest_on_stable() {
.with_stdout("")
.with_stderr(
"\
-warning: external subcommand `echo.rs` has the appearance of a manfiest-command
+warning: external subcommand `echo.rs` has the appearance of a manifest-command
This was previously accepted but will be phased out when `-Zscript` is stabilized.
For more information, see issue #12207 <https://github.com/rust-lang/cargo/issues/12207>.
",
@@ -208,11 +208,10 @@ error: running `echo.rs` requires `-Zscript`
#[cargo_test]
fn clean_output_with_edition() {
let script = r#"#!/usr/bin/env cargo
-
-//! ```cargo
-//! [package]
-//! edition = "2018"
-//! ```
+```cargo
+[package]
+edition = "2018"
+```
fn main() {
println!("Hello world!");
@@ -240,10 +239,9 @@ fn main() {
#[cargo_test]
fn warning_without_edition() {
let script = r#"#!/usr/bin/env cargo
-
-//! ```cargo
-//! [package]
-//! ```
+```cargo
+[package]
+```
fn main() {
println!("Hello world!");
@@ -625,11 +623,10 @@ fn missing_script_rs() {
fn test_name_same_as_dependency() {
Package::new("script", "1.0.0").publish();
let script = r#"#!/usr/bin/env cargo
-
-//! ```cargo
-//! [dependencies]
-//! script = "1.0.0"
-//! ```
+```cargo
+[dependencies]
+script = "1.0.0"
+```
fn main() {
println!("Hello world!");
@@ -662,11 +659,10 @@ fn main() {
#[cargo_test]
fn test_path_dep() {
let script = r#"#!/usr/bin/env cargo
-
-//! ```cargo
-//! [dependencies]
-//! bar.path = "./bar"
-//! ```
+```cargo
+[dependencies]
+bar.path = "./bar"
+```
fn main() {
println!("Hello world!");
@@ -980,6 +976,7 @@ fn cmd_clean_with_embedded() {
.with_stderr(
"\
[WARNING] `package.edition` is unspecified, defaulting to `2021`
+[REMOVED] [..] files, [..] total
",
)
.run();
diff --git a/src/tools/cargo/tests/testsuite/search.rs b/src/tools/cargo/tests/testsuite/search.rs
index 1f6f40327..4c3155c8f 100644
--- a/src/tools/cargo/tests/testsuite/search.rs
+++ b/src/tools/cargo/tests/testsuite/search.rs
@@ -89,7 +89,8 @@ fn setup() -> RegistryBuilder {
fn not_update() {
let registry = setup().build();
- use cargo::core::{Shell, Source, SourceId};
+ use cargo::core::{Shell, SourceId};
+ use cargo::sources::source::Source;
use cargo::sources::RegistrySource;
use cargo::util::Config;
@@ -172,8 +173,7 @@ fn colored_results() {
fn auth_required_failure() {
let server = setup().auth_required().no_configure_token().build();
- cargo_process("-Zregistry-auth search postgres")
- .masquerade_as_nightly_cargo(&["registry-auth"])
+ cargo_process("search postgres")
.replace_crates_io(server.index_url())
.with_status(101)
.with_stderr_contains("[ERROR] no token found, please run `cargo login`")
@@ -184,8 +184,7 @@ fn auth_required_failure() {
fn auth_required() {
let server = setup().auth_required().build();
- cargo_process("-Zregistry-auth search postgres")
- .masquerade_as_nightly_cargo(&["registry-auth"])
+ cargo_process("search postgres")
.replace_crates_io(server.index_url())
.with_stdout_contains(SEARCH_RESULTS)
.run();
diff --git a/src/tools/cargo/tests/testsuite/source_replacement.rs b/src/tools/cargo/tests/testsuite/source_replacement.rs
index 24f2ca3e3..41f3fe0b7 100644
--- a/src/tools/cargo/tests/testsuite/source_replacement.rs
+++ b/src/tools/cargo/tests/testsuite/source_replacement.rs
@@ -243,7 +243,52 @@ fn undefined_default() {
.replace_crates_io(crates_io.index_url())
.with_status(101)
.with_stderr(
- "[ERROR] no index found for registry: `undefined`
+ "[ERROR] registry index was not found in any configuration: `undefined`
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn source_replacement_with_registry_url() {
+ let alternative = RegistryBuilder::new().alternative().http_api().build();
+ Package::new("bar", "0.0.1").alternative(true).publish();
+
+ let crates_io = setup_replacement(&format!(
+ r#"
+ [source.crates-io]
+ replace-with = 'using-registry-url'
+
+ [source.using-registry-url]
+ registry = '{}'
+ "#,
+ alternative.index_url()
+ ));
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ [dependencies.bar]
+ version = "0.0.1"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check")
+ .replace_crates_io(crates_io.index_url())
+ .with_stderr(
+ "\
+[UPDATING] `using-registry-url` index
+[DOWNLOADING] crates ...
+[DOWNLOADED] bar v0.0.1 (registry `using-registry-url`)
+[CHECKING] bar v0.0.1
+[CHECKING] foo v0.0.1 ([CWD])
+[FINISHED] dev [..]
",
)
.run();
diff --git a/src/tools/cargo/tests/testsuite/ssh.rs b/src/tools/cargo/tests/testsuite/ssh.rs
index d1701d32d..f8c12819b 100644
--- a/src/tools/cargo/tests/testsuite/ssh.rs
+++ b/src/tools/cargo/tests/testsuite/ssh.rs
@@ -184,10 +184,9 @@ fn known_host_works() {
// Validate the fingerprint while we're here.
let fingerprint = stderr
.lines()
- .find(|line| line.starts_with(" The ECDSA key fingerprint"))
+ .find_map(|line| line.strip_prefix(" The ECDSA key fingerprint is: "))
.unwrap()
.trim();
- let fingerprint = &fingerprint[30..];
let finger_out = sshd.exec(&["ssh-keygen", "-l", "-f", "/etc/ssh/ssh_host_ecdsa_key.pub"]);
let gen_finger = std::str::from_utf8(&finger_out.stdout).unwrap();
// <key-size> <fingerprint> <comments…>
diff --git a/src/tools/cargo/tests/testsuite/test.rs b/src/tools/cargo/tests/testsuite/test.rs
index c6ae4ce61..5f6528109 100644
--- a/src/tools/cargo/tests/testsuite/test.rs
+++ b/src/tools/cargo/tests/testsuite/test.rs
@@ -4845,24 +4845,6 @@ error: 2 targets failed:
}
#[cargo_test]
-fn cargo_test_no_keep_going() {
- let p = project()
- .file("Cargo.toml", &basic_bin_manifest("foo"))
- .file("src/main.rs", "")
- .build();
-
- p.cargo("test --keep-going")
- .with_stderr(
- "\
-error: unexpected argument `--keep-going` found
-
- tip: to run as many tests as possible without failing fast, use `--no-fail-fast`",
- )
- .with_status(101)
- .run();
-}
-
-#[cargo_test]
fn cargo_test_print_env_verbose() {
let p = project()
.file("Cargo.toml", &basic_manifest("foo", "0.0.1"))
diff --git a/src/tools/cargo/tests/testsuite/tool_paths.rs b/src/tools/cargo/tests/testsuite/tool_paths.rs
index a211b5328..5428f9d01 100644
--- a/src/tools/cargo/tests/testsuite/tool_paths.rs
+++ b/src/tools/cargo/tests/testsuite/tool_paths.rs
@@ -32,6 +32,93 @@ fn pathless_tools() {
.run();
}
+// can set a custom linker via `target.'cfg(..)'.linker`
+#[cargo_test]
+fn custom_linker_cfg() {
+ let foo = project()
+ .file("Cargo.toml", &basic_lib_manifest("foo"))
+ .file("src/lib.rs", "")
+ .file(
+ ".cargo/config",
+ r#"
+ [target.'cfg(not(target_os = "none"))']
+ linker = "nonexistent-linker"
+ "#,
+ )
+ .build();
+
+ foo.cargo("build --verbose")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.5.0 ([CWD])
+[RUNNING] `rustc [..] -C linker=nonexistent-linker [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run();
+}
+
+// custom linker set via `target.$triple.linker` have precede over `target.'cfg(..)'.linker`
+#[cargo_test]
+fn custom_linker_cfg_precedence() {
+ let target = rustc_host();
+
+ let foo = project()
+ .file("Cargo.toml", &basic_lib_manifest("foo"))
+ .file("src/lib.rs", "")
+ .file(
+ ".cargo/config",
+ &format!(
+ r#"
+ [target.'cfg(not(target_os = "none"))']
+ linker = "ignored-linker"
+ [target.{}]
+ linker = "nonexistent-linker"
+ "#,
+ target
+ ),
+ )
+ .build();
+
+ foo.cargo("build --verbose")
+ .with_stderr(
+ "\
+[COMPILING] foo v0.5.0 ([CWD])
+[RUNNING] `rustc [..] -C linker=nonexistent-linker [..]`
+[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn custom_linker_cfg_collision() {
+ let foo = project()
+ .file("Cargo.toml", &basic_lib_manifest("foo"))
+ .file("src/lib.rs", "")
+ .file(
+ ".cargo/config",
+ r#"
+ [target.'cfg(not(target_arch = "avr"))']
+ linker = "nonexistent-linker1"
+ [target.'cfg(not(target_os = "none"))']
+ linker = "nonexistent-linker2"
+ "#,
+ )
+ .build();
+
+ foo.cargo("build --verbose")
+ .with_status(101)
+ .with_stderr(&format!(
+ "\
+[ERROR] several matching instances of `target.'cfg(..)'.linker` in configurations
+first match `cfg(not(target_arch = \"avr\"))` located in [..]/foo/.cargo/config
+second match `cfg(not(target_os = \"none\"))` located in [..]/foo/.cargo/config
+",
+ ))
+ .run();
+}
+
#[cargo_test]
fn absolute_tools() {
let target = rustc_host();
@@ -393,7 +480,6 @@ fn cfg_ignored_fields() {
[WARNING] unused key `ar` in [target] config table `cfg(not(target_os = \"none\"))`
[WARNING] unused key `foo` in [target] config table `cfg(not(target_os = \"none\"))`
[WARNING] unused key `invalid` in [target] config table `cfg(not(target_os = \"none\"))`
-[WARNING] unused key `linker` in [target] config table `cfg(not(target_os = \"none\"))`
[CHECKING] foo v0.0.1 ([..])
[FINISHED] [..]
",
diff --git a/src/tools/cargo/tests/testsuite/tree.rs b/src/tools/cargo/tests/testsuite/tree.rs
index e2e74c4f9..16cc37f7e 100644
--- a/src/tools/cargo/tests/testsuite/tree.rs
+++ b/src/tools/cargo/tests/testsuite/tree.rs
@@ -1675,7 +1675,7 @@ fn ambiguous_name() {
.with_stderr_contains(
"\
error: There are multiple `dep` packages in your project, and the specification `dep` is ambiguous.
-Please re-run this command with `-p <spec>` where `<spec>` is one of the following:
+Please re-run this command with one of the following specifications:
dep@1.0.0
dep@2.0.0
",
diff --git a/src/tools/cargo/tests/testsuite/update.rs b/src/tools/cargo/tests/testsuite/update.rs
index d42345355..fe1d86bd7 100644
--- a/src/tools/cargo/tests/testsuite/update.rs
+++ b/src/tools/cargo/tests/testsuite/update.rs
@@ -1,7 +1,7 @@
//! Tests for the `cargo update` command.
use cargo_test_support::registry::Package;
-use cargo_test_support::{basic_manifest, project};
+use cargo_test_support::{basic_lib_manifest, basic_manifest, git, project};
#[cargo_test]
fn minor_update_two_places() {
@@ -105,7 +105,7 @@ fn transitive_minor_update() {
//
// Also note that this is probably counterintuitive and weird. We may wish
// to change this one day.
- p.cargo("update -p serde")
+ p.cargo("update serde")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -155,7 +155,7 @@ fn conservative() {
Package::new("log", "0.1.1").publish();
Package::new("serde", "0.1.1").dep("log", "0.1").publish();
- p.cargo("update -p serde")
+ p.cargo("update serde")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -381,7 +381,7 @@ fn update_precise() {
Package::new("serde", "0.2.0").publish();
- p.cargo("update -p serde:0.2.1 --precise 0.2.0")
+ p.cargo("update serde:0.2.1 --precise 0.2.0")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -417,7 +417,7 @@ fn update_precise_do_not_force_update_deps() {
Package::new("log", "0.1.1").publish();
Package::new("serde", "0.2.2").dep("log", "0.1").publish();
- p.cargo("update -p serde:0.2.1 --precise 0.2.2")
+ p.cargo("update serde:0.2.1 --precise 0.2.2")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -428,7 +428,7 @@ fn update_precise_do_not_force_update_deps() {
}
#[cargo_test]
-fn update_aggressive() {
+fn update_recursive() {
Package::new("log", "0.1.0").publish();
Package::new("serde", "0.2.1").dep("log", "0.1").publish();
@@ -453,7 +453,7 @@ fn update_aggressive() {
Package::new("log", "0.1.1").publish();
Package::new("serde", "0.2.2").dep("log", "0.1").publish();
- p.cargo("update -p serde:0.2.1 --aggressive")
+ p.cargo("update serde:0.2.1 --recursive")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -465,7 +465,7 @@ fn update_aggressive() {
}
#[cargo_test]
-fn update_aggressive_conflicts_with_precise() {
+fn update_aggressive_alias_for_recursive() {
Package::new("log", "0.1.0").publish();
Package::new("serde", "0.2.1").dep("log", "0.1").publish();
@@ -490,13 +490,50 @@ fn update_aggressive_conflicts_with_precise() {
Package::new("log", "0.1.1").publish();
Package::new("serde", "0.2.2").dep("log", "0.1").publish();
- p.cargo("update -p serde:0.2.1 --precise 0.2.2 --aggressive")
+ p.cargo("update serde:0.2.1 --aggressive")
+ .with_stderr(
+ "\
+[UPDATING] `[..]` index
+[UPDATING] log v0.1.0 -> v0.1.1
+[UPDATING] serde v0.2.1 -> v0.2.2
+",
+ )
+ .run();
+}
+
+#[cargo_test]
+fn update_recursive_conflicts_with_precise() {
+ Package::new("log", "0.1.0").publish();
+ Package::new("serde", "0.2.1").dep("log", "0.1").publish();
+
+ let p = project()
+ .file(
+ "Cargo.toml",
+ r#"
+ [package]
+ name = "bar"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ serde = "0.2"
+ "#,
+ )
+ .file("src/lib.rs", "")
+ .build();
+
+ p.cargo("check").run();
+
+ Package::new("log", "0.1.1").publish();
+ Package::new("serde", "0.2.2").dep("log", "0.1").publish();
+
+ p.cargo("update serde:0.2.1 --precise 0.2.2 --recursive")
.with_status(1)
.with_stderr(
"\
-error: the argument '--precise <PRECISE>' cannot be used with '--aggressive'
+error: the argument '--precise <PRECISE>' cannot be used with '--recursive'
-Usage: cargo[EXE] update --package [<SPEC>] --precise <PRECISE>
+Usage: cargo[EXE] update --precise <PRECISE> <SPEC|--package [<SPEC>]>
For more information, try '--help'.
",
@@ -528,7 +565,7 @@ fn update_precise_first_run() {
.file("src/lib.rs", "")
.build();
- p.cargo("update -p serde --precise 0.2.0")
+ p.cargo("update serde --precise 0.2.0")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -682,7 +719,7 @@ fn update_precise_first_run() {
)
.run();
- p.cargo("update -p serde --precise 0.2.0")
+ p.cargo("update serde --precise 0.2.0")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -758,7 +795,7 @@ fn dry_run_update() {
Package::new("log", "0.1.1").publish();
Package::new("serde", "0.1.1").dep("log", "0.1").publish();
- p.cargo("update -p serde --dry-run")
+ p.cargo("update serde --dry-run")
.with_stderr(
"\
[UPDATING] `[..]` index
@@ -818,7 +855,7 @@ fn precise_with_build_metadata() {
Package::new("bar", "0.1.1+extra-stuff.1").publish();
Package::new("bar", "0.1.2+extra-stuff.2").publish();
- p.cargo("update -p bar --precise 0.1")
+ p.cargo("update bar --precise 0.1")
.with_status(101)
.with_stderr(
"\
@@ -830,7 +867,7 @@ Caused by:
)
.run();
- p.cargo("update -p bar --precise 0.1.1+does-not-match")
+ p.cargo("update bar --precise 0.1.1+does-not-match")
.with_status(101)
.with_stderr(
"\
@@ -842,7 +879,7 @@ required by package `foo v0.1.0 ([ROOT]/foo)`
)
.run();
- p.cargo("update -p bar --precise 0.1.1")
+ p.cargo("update bar --precise 0.1.1")
.with_stderr(
"\
[UPDATING] [..] index
@@ -852,7 +889,7 @@ required by package `foo v0.1.0 ([ROOT]/foo)`
.run();
Package::new("bar", "0.1.3").publish();
- p.cargo("update -p bar --precise 0.1.3+foo")
+ p.cargo("update bar --precise 0.1.3+foo")
.with_status(101)
.with_stderr(
"\
@@ -864,7 +901,7 @@ required by package `foo v0.1.0 ([ROOT]/foo)`
)
.run();
- p.cargo("update -p bar --precise 0.1.3")
+ p.cargo("update bar --precise 0.1.3")
.with_stderr(
"\
[UPDATING] [..] index
@@ -873,3 +910,185 @@ required by package `foo v0.1.0 ([ROOT]/foo)`
)
.run();
}
+
+#[cargo_test]
+fn update_only_members_order_one() {
+ let git_project = git::new("rustdns", |project| {
+ project
+ .file("Cargo.toml", &basic_lib_manifest("rustdns"))
+ .file("src/lib.rs", "pub fn bar() {}")
+ });
+
+ let workspace_toml = format!(
+ r#"
+[workspace.package]
+version = "2.29.8"
+edition = "2021"
+publish = false
+
+[workspace]
+members = [
+ "rootcrate",
+ "subcrate",
+]
+resolver = "2"
+
+[workspace.dependencies]
+# Internal crates
+subcrate = {{ version = "*", path = "./subcrate" }}
+
+# External dependencies
+rustdns = {{ version = "0.5.0", default-features = false, git = "{}" }}
+ "#,
+ git_project.url()
+ );
+ let p = project()
+ .file("Cargo.toml", &workspace_toml)
+ .file(
+ "rootcrate/Cargo.toml",
+ r#"
+[package]
+name = "rootcrate"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[dependencies]
+subcrate.workspace = true
+"#,
+ )
+ .file("rootcrate/src/main.rs", "fn main() {}")
+ .file(
+ "subcrate/Cargo.toml",
+ r#"
+[package]
+name = "subcrate"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[dependencies]
+rustdns.workspace = true
+"#,
+ )
+ .file("subcrate/src/lib.rs", "pub foo() {}")
+ .build();
+
+ // First time around we should compile both foo and bar
+ p.cargo("generate-lockfile")
+ .with_stderr(&format!(
+ "[UPDATING] git repository `{}`\n",
+ git_project.url(),
+ ))
+ .run();
+ // Modify a file manually, shouldn't trigger a recompile
+ git_project.change_file("src/lib.rs", r#"pub fn bar() { println!("hello!"); }"#);
+ // Commit the changes and make sure we don't trigger a recompile because the
+ // lock file says not to change
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+ p.change_file("Cargo.toml", &workspace_toml.replace("2.29.8", "2.29.81"));
+
+ p.cargo("update -p rootcrate")
+ .with_stderr(&format!(
+ "\
+[UPDATING] git repository `{}`
+[UPDATING] rootcrate v2.29.8 ([CWD]/rootcrate) -> v2.29.81
+[UPDATING] rustdns v0.5.0 ([..]) -> [..]
+[UPDATING] subcrate v2.29.8 ([CWD]/subcrate) -> v2.29.81",
+ git_project.url(),
+ ))
+ .run();
+}
+
+#[cargo_test]
+fn update_only_members_order_two() {
+ let git_project = git::new("rustdns", |project| {
+ project
+ .file("Cargo.toml", &basic_lib_manifest("rustdns"))
+ .file("src/lib.rs", "pub fn bar() {}")
+ });
+
+ let workspace_toml = format!(
+ r#"
+[workspace.package]
+version = "2.29.8"
+edition = "2021"
+publish = false
+
+[workspace]
+members = [
+ "crate2",
+ "crate1",
+]
+resolver = "2"
+
+[workspace.dependencies]
+# Internal crates
+crate1 = {{ version = "*", path = "./crate1" }}
+
+# External dependencies
+rustdns = {{ version = "0.5.0", default-features = false, git = "{}" }}
+ "#,
+ git_project.url()
+ );
+ let p = project()
+ .file("Cargo.toml", &workspace_toml)
+ .file(
+ "crate2/Cargo.toml",
+ r#"
+[package]
+name = "crate2"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[dependencies]
+crate1.workspace = true
+"#,
+ )
+ .file("crate2/src/main.rs", "fn main() {}")
+ .file(
+ "crate1/Cargo.toml",
+ r#"
+[package]
+name = "crate1"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[dependencies]
+rustdns.workspace = true
+"#,
+ )
+ .file("crate1/src/lib.rs", "pub foo() {}")
+ .build();
+
+ // First time around we should compile both foo and bar
+ p.cargo("generate-lockfile")
+ .with_stderr(&format!(
+ "[UPDATING] git repository `{}`\n",
+ git_project.url(),
+ ))
+ .run();
+ // Modify a file manually, shouldn't trigger a recompile
+ git_project.change_file("src/lib.rs", r#"pub fn bar() { println!("hello!"); }"#);
+ // Commit the changes and make sure we don't trigger a recompile because the
+ // lock file says not to change
+ let repo = git2::Repository::open(&git_project.root()).unwrap();
+ git::add(&repo);
+ git::commit(&repo);
+ p.change_file("Cargo.toml", &workspace_toml.replace("2.29.8", "2.29.81"));
+
+ p.cargo("update -p crate2")
+ .with_stderr(&format!(
+ "\
+[UPDATING] git repository `{}`
+[UPDATING] crate1 v2.29.8 ([CWD]/crate1) -> v2.29.81
+[UPDATING] crate2 v2.29.8 ([CWD]/crate2) -> v2.29.81
+[UPDATING] rustdns v0.5.0 ([..]) -> [..]",
+ git_project.url(),
+ ))
+ .run();
+}
diff --git a/src/tools/cargo/tests/testsuite/workspaces.rs b/src/tools/cargo/tests/testsuite/workspaces.rs
index c6698f76a..4f8997b38 100644
--- a/src/tools/cargo/tests/testsuite/workspaces.rs
+++ b/src/tools/cargo/tests/testsuite/workspaces.rs
@@ -1091,9 +1091,6 @@ fn new_warning_with_corrupt_ws() {
failed to parse manifest at `[..]foo/Cargo.toml`
Caused by:
- could not parse input as TOML
-
-Caused by:
TOML parse error at line 1, column 5
|
1 | asdf
diff --git a/src/tools/cargo/tests/testsuite/yank.rs b/src/tools/cargo/tests/testsuite/yank.rs
index c0bd24776..9aff2fc84 100644
--- a/src/tools/cargo/tests/testsuite/yank.rs
+++ b/src/tools/cargo/tests/testsuite/yank.rs
@@ -76,14 +76,14 @@ fn explicit_version_with_asymmetric() {
// The http_api server will check that the authorization is correct.
// If the authorization was not sent then we would get an unauthorized error.
p.cargo("yank --version 0.0.1")
- .arg("-Zcredential-process")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ .arg("-Zasymmetric-token")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
.replace_crates_io(registry.index_url())
.run();
p.cargo("yank --undo --version 0.0.1")
- .arg("-Zcredential-process")
- .masquerade_as_nightly_cargo(&["credential-process"])
+ .arg("-Zasymmetric-token")
+ .masquerade_as_nightly_cargo(&["asymmetric-token"])
.replace_crates_io(registry.index_url())
.run();
}
diff --git a/src/tools/cargo/triagebot.toml b/src/tools/cargo/triagebot.toml
index 6d07f438f..c92b4ce8c 100644
--- a/src/tools/cargo/triagebot.toml
+++ b/src/tools/cargo/triagebot.toml
@@ -86,6 +86,9 @@ trigger_files = ["src/cargo/core/dependency.rs"]
[autolabel."A-crate-types"]
trigger_files = ["src/cargo/core/compiler/crate_type.rs"]
+[autolabel."A-credential-provider"]
+trigger_files = ["credential/"]
+
[autolabel."A-dep-info"]
trigger_files = ["src/cargo/core/compiler/output_depinfo.rs"]
@@ -123,6 +126,9 @@ trigger_files = ["src/cargo/core/compiler/future_incompat.rs"]
[autolabel."A-git"]
trigger_files = ["src/cargo/sources/git/"]
+[autolabel."A-home"]
+trigger_files = ["crates/home/"]
+
[autolabel."A-infrastructure"]
trigger_files = [
".cargo/",
@@ -180,7 +186,7 @@ trigger_files = ["src/cargo/core/compiler/fingerprint/"]
trigger_files = ["src/cargo/sources/registry/", "src/cargo/core/registry.rs"]
[autolabel."A-registry-authentication"]
-trigger_files = ["src/cargo/util/auth/", "credential/"]
+trigger_files = ["src/cargo/util/auth/"]
[autolabel."A-semver"]
trigger_files = [