diff --git a/.cargo/config.toml b/.cargo/config.toml index c4cd35e56bc9..f1a267084187 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -2,6 +2,7 @@ build-man = "run --package xtask-build-man --" stale-label = "run --package xtask-stale-label --" bump-check = "run --package xtask-bump-check --" +lint-docs = "run --package xtask-lint-docs --" [env] # HACK: Until this is stabilized, `snapbox`s polyfill could get confused diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e680a32d61fa..de81970f67db 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -83,6 +83,13 @@ jobs: - run: rustup update stable && rustup default stable - run: cargo stale-label + lint-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update stable && rustup default stable + - run: cargo lint-docs --check + # Ensure Cargo.lock is up-to-date lockfile: runs-on: ubuntu-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 5920bac277d3..2fec28b78ccf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,23 +1,235 @@ # Changelog +## Cargo 1.81 (2024-09-05) +[34a6a87d...HEAD](https://github.com/rust-lang/cargo/compare/34a6a87d...HEAD) + +### Added + +### Changed + +- ❗️ cargo-package: Disallow `package.license-file` and `package.readme` pointing + to non-existent files during packaging. +- ❗️ Disallow passing `--release`/`--debug` flag along with the `--profile` flag. + [#13971](https://github.com/rust-lang/cargo/pull/13971) + [#13921](https://github.com/rust-lang/cargo/pull/13921) +- ❗️ Remove `lib.plugin` key support in Cargo.toml. + Rust plugin support has been deprecated for four years and was removed in 1.75.0. + [#13902](https://github.com/rust-lang/cargo/pull/13902) + [#14038](https://github.com/rust-lang/cargo/pull/14038) + +### Fixed + +- Fix a proc-macro example from a dependency affecting feature resolution. + [#13892](https://github.com/rust-lang/cargo/pull/13892) + +### Nightly only + +- 🔥 `update-breaking`: Add `--breaking` to `cargo update`, + allowing upgrading dependencies to breaking versions. + [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#update-breaking) + [#13979](https://github.com/rust-lang/cargo/pull/13979) +- `--artifact-dir`: Rename `--out-dir` to `--artifact-dir`. + The `--out-dir` flag is kept for compatibility + and may be removed when the feature gets stabilized. + [#13809](https://github.com/rust-lang/cargo/pull/13809) +- `edition2024`: Ensure unused optional dependencies fire for shadowed dependencies. + [#14028](https://github.com/rust-lang/cargo/pull/14028) +- `-Zcargo-lints`: Add `unknown_lints` to lints list. + [#14024](https://github.com/rust-lang/cargo/pull/14024) +- `-Zcargo-lints`: Add tooling to document lints. + [#14025](https://github.com/rust-lang/cargo/pull/14025) +- `-Zcargo-lints`: Keep lints updated and sorted. + [#14030](https://github.com/rust-lang/cargo/pull/14030) +- cargo-update: Track the behavior of `--precise `. + [#14013](https://github.com/rust-lang/cargo/pull/14013) + +### Documentation + +- contrib: Suggest atomic commits with separate test commits. + [#14014](https://github.com/rust-lang/cargo/pull/14014) + +### Internal + +- Remove the temporary `__CARGO_GITOXIDE_DISABLE_LIST_FILES` environment variable. + [#14036](https://github.com/rust-lang/cargo/pull/14036) +- Update dependencies. + [#13995](https://github.com/rust-lang/cargo/pull/13995) + [#13998](https://github.com/rust-lang/cargo/pull/13998) + [#14037](https://github.com/rust-lang/cargo/pull/14037) + ## Cargo 1.80 (2024-07-25) -[b60a1555...HEAD](https://github.com/rust-lang/cargo/compare/b60a1555...HEAD) +[b60a1555...rust-1.80.0](https://github.com/rust-lang/cargo/compare/b60a1555...rust-1.80.0) ### Added +- 🎉 Stabilize `-Zcheck-cfg`! This by default enables rustc's checking of + conditional compilation at compile time, which verifies that the crate is + correctly handling conditional compilation for different target platforms or + features. Internally, cargo will be passing a new command line option + `--check-cfg` to all rustc and rustdoc invocations. + + A new build script invocation + [`cargo::rustc-check-cfg=CHECK_CFG`](https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg) + is added along with this stabilization, as a way to add custom cfgs to the + list of expected cfg names and values. + + If a build script is not an option for your package, Cargo provides a config + [`[lints.rust.unexpected_cfgs.check-cfg]`](https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html#check-cfg-in-lintsrust-table) + to add known custom cfgs statically. + + ([RFC 3013](https://github.com/rust-lang/rfcs/blob/master/text/3013-conditional-compilation-checking.md)) + ([docs](https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html)) + [#13571](https://github.com/rust-lang/cargo/pull/13571) + [#13865](https://github.com/rust-lang/cargo/pull/13865) + [#13869](https://github.com/rust-lang/cargo/pull/13869) + [#13884](https://github.com/rust-lang/cargo/pull/13884) + [#13913](https://github.com/rust-lang/cargo/pull/13913) + [#13937](https://github.com/rust-lang/cargo/pull/13937) + [#13958](https://github.com/rust-lang/cargo/pull/13958) + +- 🎉 cargo-update: Allows `--precise` to specify a yanked version of a package, + and will update the lockfile accordingly. + [#13974](https://github.com/rust-lang/cargo/pull/13974) + ### Changed +- ❗️ manifest: Disallow `[badges]` to inherit from `[workspace.package.badges]`. + This was considered a bug. + Keep in mind that `[badges]` is effectively deprecated. + [#13788](https://github.com/rust-lang/cargo/pull/13788) +- build-script: Suggest old syntax based on MSRV. + [#13874](https://github.com/rust-lang/cargo/pull/13874) +- cargo-add: Avoid escaping double quotes by using string literals. + [#14006](https://github.com/rust-lang/cargo/pull/14006) +- cargo-clean: Performance improvements for cleaning specific packages via `-p` flag. + [#13818](https://github.com/rust-lang/cargo/pull/13818) +- cargo-new: Use `i32` rather than `usize` as the "default integer" in library template. + [#13939](https://github.com/rust-lang/cargo/pull/13939) +- cargo-package: Warn, rather than fail, if a Cargo target is excluded during packaging. + [#13713](https://github.com/rust-lang/cargo/pull/13713) +- manifest: Warn, not error, on unsupported lint tool in the `[lints]` table. + [#13833](https://github.com/rust-lang/cargo/pull/13833) +- perf: Avoid inferring when Cargo targets are known. + [#13849](https://github.com/rust-lang/cargo/pull/13849) +- Populate git information when building Cargo from Rust's source tarball. + [#13832](https://github.com/rust-lang/cargo/pull/13832) +- Improve the error message when deserializing Cargo configuration from partial environment variables. + [#13956](https://github.com/rust-lang/cargo/pull/13956) + ### Fixed +- resolver: Make path dependencies with the same name stay locked. + [#13572](https://github.com/rust-lang/cargo/pull/13572) +- cargo-add: Preserve file permissions on Unix during `write_atomic`. + [#13898](https://github.com/rust-lang/cargo/pull/13898) +- cargo-clean: Remove symlink directory on Windows. + [#13910](https://github.com/rust-lang/cargo/pull/13910) +- cargo-fix: Don't fix into the standard library. + [#13792](https://github.com/rust-lang/cargo/pull/13792) +- cargo-fix: Support IPv6-only networks. + [#13907](https://github.com/rust-lang/cargo/pull/13907) +- cargo-new: Don't say we're adding to a workspace when a regular package is in the root. + [#13987](https://github.com/rust-lang/cargo/pull/13987) +- cargo-vendor: Silence the warning about forgetting the vendoring. + [#13886](https://github.com/rust-lang/cargo/pull/13886) +- cargo-publish/cargo-vendor: Ensure targets in generated Cargo.toml are in a deterministic order. + [#13989](https://github.com/rust-lang/cargo/pull/13989) + [#14004](https://github.com/rust-lang/cargo/pull/14004) +- cargo-credential-libsecret: Load `libsecret` by its `SONAME`, `libsecret-1.so.0`. + [#13927](https://github.com/rust-lang/cargo/pull/13927) +- Don't panic when an alias doesn't include a subcommand. + [#13819](https://github.com/rust-lang/cargo/pull/13819) +- Workaround copying file returning EAGAIN on ZFS on macOS. + [#13845](https://github.com/rust-lang/cargo/pull/13845) +- Fetch specific commits even if the GitHub fast path fails. + [#13946](https://github.com/rust-lang/cargo/pull/13946) + [#13969](https://github.com/rust-lang/cargo/pull/13969) +- Distinguish Cargo config from different environment variables that share the same prefix. + [#14000](https://github.com/rust-lang/cargo/pull/14000) + ### Nightly only - `-Zcargo-lints`: Don't always inherit workspace lints. [#13812](https://github.com/rust-lang/cargo/pull/13812) +- `-Zcargo-lints`: Add a test to ensure cap-lints works. + [#13829](https://github.com/rust-lang/cargo/pull/13829) +- `-Zcargo-lints`: Error when unstable lints are specified but not enabled. + [#13805](https://github.com/rust-lang/cargo/pull/13805) +- `-Zcargo-lints`: Add cargo-lints to unstable docs. + [#13881](https://github.com/rust-lang/cargo/pull/13881) +- `-Zcargo-lints`: Refactor cargo lint tests. + [#13880](https://github.com/rust-lang/cargo/pull/13880) +- `-Zcargo-lints`: Remove ability to specify `-` in lint name. + [#13837](https://github.com/rust-lang/cargo/pull/13837) +- `-Zscript`: Remove unstable rejected frontmatter syntax for cargo script. + The only allowed frontmatter syntax now is `---`. + [#13861](https://github.com/rust-lang/cargo/pull/13861) + [#13893](https://github.com/rust-lang/cargo/pull/13893) +- `-Zbindeps`: Build only the specified artifact library when multiple types are available. + [#13842](https://github.com/rust-lang/cargo/pull/13842) +- `-Zmsrv-policy`: Treat unset MSRV as compatible. + [#13791](https://github.com/rust-lang/cargo/pull/13791) +- `-Zgit`/`-Zgitoxide`: Default configuration to be obtained from both environment variables and Cargo configuration. + [#13687](https://github.com/rust-lang/cargo/pull/13687) +- `-Zpublic-dependency`: Don't lose 'public' when inheriting a dependency. + [#13836](https://github.com/rust-lang/cargo/pull/13836) +- `edition2024`: Disallow ignored `default-features` when inheriting. + [#13839](https://github.com/rust-lang/cargo/pull/13839) +- `edition2024`: Validate crate-types/proc-macro for bin like other Cargo targets. + [#13841](https://github.com/rust-lang/cargo/pull/13841) ### Documentation +- cargo-package: Clarify no guarantee of VCS provenance. + [#13984](https://github.com/rust-lang/cargo/pull/13984) +- cargo-metadata: Clarify dash replacement rule in Cargo target names. + [#13887](https://github.com/rust-lang/cargo/pull/13887) +- config: Fix wrong type of `rustc-flags` in build script overrides. + [#13957](https://github.com/rust-lang/cargo/pull/13957) +- resolver: Add README for `resolver-tests`. + [#13977](https://github.com/rust-lang/cargo/pull/13977) +- contrib: Update UI example code in contributor guide. + [#13864](https://github.com/rust-lang/cargo/pull/13864) +- Fix libcurl proxy documentation link. + [#13990](https://github.com/rust-lang/cargo/pull/13990) +- Add missing `CARGO_MAKEFLAGS` env for plugins. + [#13872](https://github.com/rust-lang/cargo/pull/13872) +- Include CircleCI reference in the Continuous Integration chapter. + [#13850](https://github.com/rust-lang/cargo/pull/13850) + ### Internal +- ci: Don't check `cargo` against beta channel. + [#13827](https://github.com/rust-lang/cargo/pull/13827) +- test: Set safe.directory for git repo in apache container. + [#13920](https://github.com/rust-lang/cargo/pull/13920) +- test: Silence warnings running embedded unittests. + [#13929](https://github.com/rust-lang/cargo/pull/13929) +- test: Update test formatting due to nightly rustc changes. + [#13890](https://github.com/rust-lang/cargo/pull/13890) + [#13901](https://github.com/rust-lang/cargo/pull/13901) + [#13964](https://github.com/rust-lang/cargo/pull/13964) +- test: Make `git::use_the_cli` test truly locale independent. + [#13935](https://github.com/rust-lang/cargo/pull/13935) +- cargo-test-support: Transition direct assertions from cargo-test-support to snapbox. + [#13980](https://github.com/rust-lang/cargo/pull/13980) +- cargo-test-support: Auto-redact elapsed time. + [#13973](https://github.com/rust-lang/cargo/pull/13973) +- cargo-test-support: Clean up unnecessary uses of `match_exact`. + [#13879](https://github.com/rust-lang/cargo/pull/13879) +- Split `RecursivePathSource` out of `PathSource`. + [#13993](https://github.com/rust-lang/cargo/pull/13993) +- Adjust custom errors from cert-check due to libgit2 1.8 change. + [#13970](https://github.com/rust-lang/cargo/pull/13970) +- Move diagnostic printing to Shell. + [#13813](https://github.com/rust-lang/cargo/pull/13813) +- Update dependencies. + [#13834](https://github.com/rust-lang/cargo/pull/13834) + [#13840](https://github.com/rust-lang/cargo/pull/13840) + [#13948](https://github.com/rust-lang/cargo/pull/13948) + [#13963](https://github.com/rust-lang/cargo/pull/13963) + [#13976](https://github.com/rust-lang/cargo/pull/13976) + ## Cargo 1.79 (2024-06-13) [2fe739fc...rust-1.79.0](https://github.com/rust-lang/cargo/compare/2fe739fc...rust-1.79.0) @@ -65,6 +277,8 @@ [#13664](https://github.com/rust-lang/cargo/pull/13664) - Emit 1.77 build script syntax error only when msrv is incompatible. [#13808](https://github.com/rust-lang/cargo/pull/13808) +- Don't warn on `lints.rust.unexpected_cfgs.check-cfg`. + [#13925](https://github.com/rust-lang/cargo/pull/13925) - cargo-init: don't assign `target.name` in Cargo.toml if the value can be inferred. [#13606](https://github.com/rust-lang/cargo/pull/13606) - cargo-package: normalize paths in `Cargo.toml`, including replacing `\` with `/`. @@ -74,6 +288,9 @@ ### Fixed +- Ensure `--config net.git-fetch-with-cli=true` is respected. + [#13992](https://github.com/rust-lang/cargo/pull/13992) + [#13997](https://github.com/rust-lang/cargo/pull/13997) - Dont panic when resolving an empty alias. [#13613](https://github.com/rust-lang/cargo/pull/13613) - When using `--target`, the default debuginfo strip rule also applies. @@ -118,6 +335,8 @@ [#13797](https://github.com/rust-lang/cargo/pull/13797) [#13740](https://github.com/rust-lang/cargo/pull/13740) [#13801](https://github.com/rust-lang/cargo/pull/13801) + [#13852](https://github.com/rust-lang/cargo/pull/13852) + [#13853](https://github.com/rust-lang/cargo/pull/13853) - 🔥 `edition2024`: Add default Edition2024 to resolver v3 (MSRV-aware resolver). [#13785](https://github.com/rust-lang/cargo/pull/13785) - `edition2024`: Remove underscore field support in 2024. @@ -190,6 +409,7 @@ [#13692](https://github.com/rust-lang/cargo/pull/13692) [#13731](https://github.com/rust-lang/cargo/pull/13731) [#13760](https://github.com/rust-lang/cargo/pull/13760) + [#13950](https://github.com/rust-lang/cargo/pull/13950) ## Cargo 1.78 (2024-05-02) [7bb7b539...rust-1.78.0](https://github.com/rust-lang/cargo/compare/7bb7b539...rust-1.78.0) diff --git a/Cargo.lock b/Cargo.lock index e2a42023b9c6..90a7e3779b3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,9 +43,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "annotate-snippets" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5a59f105fb9635e9eebdc1e29d53e764fa5795b9cf899a638a53e61567ef61" +checksum = "086b0afab3b349e5691143adbfb26983821e3eec4ba4c51957104d372c2e1b7d" dependencies = [ "anstyle", "unicode-width", @@ -53,23 +53,24 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-lossy" @@ -123,9 +124,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arc-swap" @@ -265,7 +266,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.81.0" +version = "0.82.0" dependencies = [ "annotate-snippets", "anstream", @@ -301,7 +302,7 @@ dependencies = [ "ignore", "im-rc", "indexmap", - "itertools 0.12.1", + "itertools 0.13.0", "jobserver", "lazycell", "libc", @@ -412,7 +413,7 @@ version = "0.2.1" [[package]] name = "cargo-test-support" -version = "0.2.1" +version = "0.2.2" dependencies = [ "anstream", "anstyle", @@ -424,7 +425,7 @@ dependencies = [ "flate2", "git2", "glob", - "itertools 0.12.1", + "itertools 0.13.0", "pasetors", "regex", "serde", @@ -461,7 +462,7 @@ dependencies = [ [[package]] name = "cargo-util-schemas" -version = "0.4.0" +version = "0.5.0" dependencies = [ "semver", "serde", @@ -539,18 +540,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.4" +version = "4.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "a9689a29b593160de5bc4aacab7b5d54fb52231de70122626c178e6a368994c7" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "2e5387378c84f6faa26890ebf9f0a92989f8873d4d380467bcd0d8d8620424df" dependencies = [ "anstream", "anstyle", @@ -2052,6 +2053,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.10.5" @@ -2063,9 +2070,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -2129,9 +2136,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libdbus-sys" @@ -2388,9 +2395,9 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opener" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9901cb49d7fc923b256db329ee26ffed69130bf05d74b9efdd1875c92d6af01" +checksum = "f8df34be653210fbe9ffaff41d3b92721c56ce82dfee58ee684f9afb5e3a90c0" dependencies = [ "bstr", "dbus", @@ -2741,9 +2748,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.10.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" +checksum = "8746739f11d39ce5ad5c2520a9b75285310dbfe78c541ccf832d38615765aec0" dependencies = [ "bitflags 2.5.0", "memchr", @@ -2753,9 +2760,9 @@ dependencies = [ [[package]] name = "pulldown-cmark-escape" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d8f9aa0e3cbcfaf8bf00300004ee3b72f74770f9cbac93f6928771f613276b" +checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" [[package]] name = "quick-error" @@ -2851,9 +2858,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -3020,11 +3027,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -3033,9 +3040,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -3043,9 +3050,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] @@ -3059,21 +3066,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.199" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde-untagged" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a160535368dfc353348e7eaa299156bd508c60c45a9249725f5f6d370d82a66" +checksum = "2676ba99bd82f75cae5cbd2c8eda6fa0b8760f18978ea840e980dd5567b5c5b6" dependencies = [ "erased-serde", "serde", + "typeid", ] [[package]] @@ -3088,9 +3096,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.199" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", @@ -3108,9 +3116,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa 1.0.11", "ryu", @@ -3209,9 +3217,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "snapbox" -version = "0.6.7" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94204b12a4d3550420babdb4148c6639692e4e3e61060866929c5107f208aeb6" +checksum = "9e5cb88aa548c9514cd7dba04a5d8d80a9464ae6d04a1d203fa7d469c71b75e9" dependencies = [ "anstream", "anstyle", @@ -3222,6 +3230,7 @@ dependencies = [ "filetime", "normalize-line-endings", "regex", + "serde", "serde_json", "similar", "snapbox-macros", @@ -3324,9 +3333,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" dependencies = [ "filetime", "libc", @@ -3356,18 +3365,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", @@ -3548,6 +3557,12 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "typeid" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "059d83cc991e7a42fc37bd50941885db0888e34209f8cfd9aab07ddec03bc9cf" + [[package]] name = "typenum" version = "1.17.0" @@ -3604,9 +3619,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -4021,6 +4036,16 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "xtask-lint-docs" +version = "0.1.0" +dependencies = [ + "anyhow", + "cargo", + "clap", + "itertools 0.13.0", +] + [[package]] name = "xtask-stale-label" version = "0.0.0" diff --git a/Cargo.toml b/Cargo.toml index ae1f13a62abf..ebc6d5f15a2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ cargo-platform = { path = "crates/cargo-platform", version = "0.1.5" } cargo-test-macro = { version = "0.2.0", path = "crates/cargo-test-macro" } cargo-test-support = { version = "0.2.0", path = "crates/cargo-test-support" } cargo-util = { version = "0.2.9", path = "crates/cargo-util" } -cargo-util-schemas = { version = "0.4.0", path = "crates/cargo-util-schemas" } +cargo-util-schemas = { version = "0.5.0", path = "crates/cargo-util-schemas" } cargo_metadata = "0.18.1" clap = "4.5.4" color-print = "0.3.6" @@ -57,7 +57,7 @@ humantime = "2.1.0" ignore = "0.4.22" im-rc = "15.1.0" indexmap = "2.2.6" -itertools = "0.12.1" +itertools = "0.13.0" jobserver = "0.1.31" lazycell = "1.3.0" libc = "0.2.154" @@ -74,7 +74,7 @@ pathdiff = "0.2.1" percent-encoding = "2.3.1" pkg-config = "0.3.30" proptest = "1.4.0" -pulldown-cmark = { version = "0.10.3", default-features = false, features = ["html"] } +pulldown-cmark = { version = "0.11.0", default-features = false, features = ["html"] } rand = "0.8.5" regex = "1.10.4" rusqlite = { version = "0.31.0", features = ["bundled"] } @@ -91,7 +91,7 @@ sha1 = "0.10.6" sha2 = "0.10.8" shell-escape = "0.1.5" supports-hyperlinks = "3.0.0" -snapbox = { version = "0.6.7", features = ["diff", "dir", "term-svg", "regex"] } +snapbox = { version = "0.6.9", features = ["diff", "dir", "term-svg", "regex", "json"] } tar = { version = "0.4.40", default-features = false } tempfile = "3.10.1" thiserror = "1.0.59" @@ -125,7 +125,7 @@ self_named_module_files = "warn" [package] name = "cargo" -version = "0.81.0" +version = "0.82.0" edition.workspace = true license.workspace = true rust-version = "1.78" # MSRV:1 diff --git a/benches/benchsuite/benches/resolve.rs b/benches/benchsuite/benches/resolve.rs index 89d0212e378c..d798dd6d62bb 100644 --- a/benches/benchsuite/benches/resolve.rs +++ b/benches/benchsuite/benches/resolve.rs @@ -33,6 +33,7 @@ fn do_resolve<'gctx>(gctx: &'gctx GlobalContext, ws_root: &Path) -> ResolveInfo< let force_all_targets = ForceAllTargets::No; // Do an initial run to download anything necessary so that it does // not confuse criterion's warmup. + let dry_run = false; let ws_resolve = cargo::ops::resolve_ws_with_opts( &ws, &mut target_data, @@ -41,6 +42,7 @@ fn do_resolve<'gctx>(gctx: &'gctx GlobalContext, ws_root: &Path) -> ResolveInfo< &specs, has_dev_units, force_all_targets, + dry_run, ) .unwrap(); ResolveInfo { @@ -71,6 +73,7 @@ fn resolve_ws(c: &mut Criterion) { // iterator once, and we don't want to call `do_resolve` in every // "step", since that would just be some useless work. let mut lazy_info = None; + let dry_run = false; group.bench_function(&ws_name, |b| { let ResolveInfo { ws, @@ -91,6 +94,7 @@ fn resolve_ws(c: &mut Criterion) { specs, *has_dev_units, *force_all_targets, + dry_run, ) .unwrap(); }) diff --git a/crates/cargo-test-support/Cargo.toml b/crates/cargo-test-support/Cargo.toml index 9d6ca7303ef8..a8d5025f8de7 100644 --- a/crates/cargo-test-support/Cargo.toml +++ b/crates/cargo-test-support/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cargo-test-support" -version = "0.2.1" +version = "0.2.2" edition.workspace = true rust-version = "1.78" # MSRV:1 license.workspace = true diff --git a/crates/cargo-test-support/src/compare.rs b/crates/cargo-test-support/src/compare.rs index 53b752621de8..9a7f93bc557e 100644 --- a/crates/cargo-test-support/src/compare.rs +++ b/crates/cargo-test-support/src/compare.rs @@ -36,8 +36,9 @@ //! a problem. //! - Carriage returns are removed, which can help when running on Windows. -use crate::diff; +use crate::cross_compile::try_alternate; use crate::paths; +use crate::{diff, rustc_host}; use anyhow::{bail, Context, Result}; use serde_json::Value; use std::fmt; @@ -45,6 +46,15 @@ use std::path::Path; use std::str; use url::Url; +/// This makes it easier to write regex replacements that are guaranteed to only +/// get compiled once +macro_rules! regex { + ($re:literal $(,)?) => {{ + static RE: std::sync::OnceLock = std::sync::OnceLock::new(); + RE.get_or_init(|| regex::Regex::new($re).unwrap()) + }}; +} + /// Assertion policy for UI tests /// /// This emphasizes showing as much content as possible at the cost of more brittleness @@ -77,21 +87,8 @@ use url::Url; /// a problem. /// - Carriage returns are removed, which can help when running on Windows. pub fn assert_ui() -> snapbox::Assert { - let root = paths::root(); - // Use `from_file_path` instead of `from_dir_path` so the trailing slash is - // put in the users output, rather than hidden in the variable - let root_url = url::Url::from_file_path(&root).unwrap().to_string(); - let mut subs = snapbox::Redactions::new(); - subs.extend(MIN_LITERAL_REDACTIONS.into_iter().cloned()) - .unwrap(); - subs.insert("[ROOT]", root).unwrap(); - subs.insert("[ROOTURL]", root_url).unwrap(); - subs.insert( - "[ELAPSED]", - regex::Regex::new("Finished.*in (?[0-9]+(\\.[0-9]+))s").unwrap(), - ) - .unwrap(); + add_common_redactions(&mut subs); snapbox::Assert::new() .action_env(snapbox::assert::DEFAULT_ACTION_ENV) .redact_with(subs) @@ -129,32 +126,80 @@ pub fn assert_ui() -> snapbox::Assert { /// a problem. /// - Carriage returns are removed, which can help when running on Windows. pub fn assert_e2e() -> snapbox::Assert { + let mut subs = snapbox::Redactions::new(); + add_common_redactions(&mut subs); + subs.extend(E2E_LITERAL_REDACTIONS.into_iter().cloned()) + .unwrap(); + + snapbox::Assert::new() + .action_env(snapbox::assert::DEFAULT_ACTION_ENV) + .redact_with(subs) +} + +fn add_common_redactions(subs: &mut snapbox::Redactions) { let root = paths::root(); // Use `from_file_path` instead of `from_dir_path` so the trailing slash is // put in the users output, rather than hidden in the variable let root_url = url::Url::from_file_path(&root).unwrap().to_string(); - let mut subs = snapbox::Redactions::new(); subs.extend(MIN_LITERAL_REDACTIONS.into_iter().cloned()) .unwrap(); - subs.extend(E2E_LITERAL_REDACTIONS.into_iter().cloned()) - .unwrap(); subs.insert("[ROOT]", root).unwrap(); subs.insert("[ROOTURL]", root_url).unwrap(); + // For e2e tests subs.insert( "[ELAPSED]", - regex::Regex::new("[FINISHED].*in (?[0-9]+(\\.[0-9]+))s").unwrap(), + regex!("[FINISHED].*in (?[0-9]+(\\.[0-9]+))s"), + ) + .unwrap(); + // for UI tests + subs.insert( + "[ELAPSED]", + regex!("Finished.*in (?[0-9]+(\\.[0-9]+))s"), + ) + .unwrap(); + // output from libtest + subs.insert( + "[ELAPSED]", + regex!("; finished in (?[0-9]+(\\.[0-9]+))s"), + ) + .unwrap(); + subs.insert( + "[FILE_SIZE]", + regex!("(?[0-9]+(\\.[0-9]+)([a-zA-Z]i)?)B"), + ) + .unwrap(); + subs.insert( + "[HASH]", + regex!("home/\\.cargo/registry/src/-(?[a-z0-9]+)"), + ) + .unwrap(); + subs.insert("[HASH]", regex!("/[a-z0-9\\-_]+-(?[0-9a-f]{16})")) + .unwrap(); + subs.insert("[HOST_TARGET]", rustc_host()).unwrap(); + if let Some(alt_target) = try_alternate() { + subs.insert("[ALT_TARGET]", alt_target).unwrap(); + } + subs.insert( + "[AVG_ELAPSED]", + regex!("(?[0-9]+(\\.[0-9]+)?) ns/iter"), + ) + .unwrap(); + subs.insert( + "[JITTER]", + regex!("ns/iter \\(\\+/- (?[0-9]+(\\.[0-9]+)?)\\)"), ) .unwrap(); - snapbox::Assert::new() - .action_env(snapbox::assert::DEFAULT_ACTION_ENV) - .redact_with(subs) } static MIN_LITERAL_REDACTIONS: &[(&str, &str)] = &[ ("[EXE]", std::env::consts::EXE_SUFFIX), ("[BROKEN_PIPE]", "Broken pipe (os error 32)"), ("[BROKEN_PIPE]", "The pipe is being closed. (os error 232)"), + // Unix message for exit status + ("[EXIT_STATUS]", "exit status"), + // Windows message for exit status + ("[EXIT_STATUS]", "exit code"), ]; static E2E_LITERAL_REDACTIONS: &[(&str, &str)] = &[ ("[RUNNING]", " Running"), @@ -176,6 +221,7 @@ static E2E_LITERAL_REDACTIONS: &[(&str, &str)] = &[ ("[DIRTY]", " Dirty"), ("[LOCKING]", " Locking"), ("[UPDATING]", " Updating"), + ("[UPGRADING]", " Upgrading"), ("[ADDING]", " Adding"), ("[REMOVING]", " Removing"), ("[REMOVED]", " Removed"), diff --git a/crates/cargo-test-support/src/cross_compile.rs b/crates/cargo-test-support/src/cross_compile.rs index a2daf882d9dc..beda66165504 100644 --- a/crates/cargo-test-support/src/cross_compile.rs +++ b/crates/cargo-test-support/src/cross_compile.rs @@ -209,18 +209,23 @@ pub fn native_arch() -> &'static str { /// /// Only use this function on tests that check `cross_compile::disabled`. pub fn alternate() -> &'static str { + try_alternate().expect("This test should be gated on cross_compile::disabled.") +} + +/// A possible alternate target-triple to build with. +pub(crate) fn try_alternate() -> Option<&'static str> { if cfg!(all(target_os = "macos", target_arch = "aarch64")) { - "x86_64-apple-darwin" + Some("x86_64-apple-darwin") } else if cfg!(target_os = "macos") { - "x86_64-apple-ios" + Some("x86_64-apple-ios") } else if cfg!(target_os = "linux") { - "i686-unknown-linux-gnu" + Some("i686-unknown-linux-gnu") } else if cfg!(all(target_os = "windows", target_env = "msvc")) { - "i686-pc-windows-msvc" + Some("i686-pc-windows-msvc") } else if cfg!(all(target_os = "windows", target_env = "gnu")) { - "i686-pc-windows-gnu" + Some("i686-pc-windows-gnu") } else { - panic!("This test should be gated on cross_compile::disabled."); + None } } diff --git a/crates/cargo-test-support/src/lib.rs b/crates/cargo-test-support/src/lib.rs index 5db67b8ea900..09644298316b 100644 --- a/crates/cargo-test-support/src/lib.rs +++ b/crates/cargo-test-support/src/lib.rs @@ -25,6 +25,7 @@ use std::time::{self, Duration}; use anyhow::{bail, Result}; use cargo_util::{is_ci, ProcessBuilder, ProcessError}; +use snapbox::IntoData as _; use url::Url; use self::paths::CargoPathExt; @@ -534,6 +535,8 @@ pub struct Execs { expect_stdin: Option, expect_stderr: Option, expect_exit_code: Option, + expect_stdout_data: Option, + expect_stderr_data: Option, expect_stdout_contains: Vec, expect_stderr_contains: Vec, expect_stdout_contains_n: Vec<(String, usize)>, @@ -545,6 +548,7 @@ pub struct Execs { expect_json: Option, expect_json_contains_unordered: Option, stream_output: bool, + assert: snapbox::Assert, } impl Execs { @@ -555,6 +559,7 @@ impl Execs { /// Verifies that stdout is equal to the given lines. /// See [`compare`] for supported patterns. + #[deprecated(note = "replaced with `Execs::with_stdout_data(expected)`")] pub fn with_stdout(&mut self, expected: S) -> &mut Self { self.expect_stdout = Some(expected.to_string()); self @@ -562,11 +567,28 @@ impl Execs { /// Verifies that stderr is equal to the given lines. /// See [`compare`] for supported patterns. + #[deprecated(note = "replaced with `Execs::with_stderr_data(expected)`")] pub fn with_stderr(&mut self, expected: S) -> &mut Self { self.expect_stderr = Some(expected.to_string()); self } + /// Verifies that stdout is equal to the given lines. + /// + /// See [`compare::assert_e2e`] for assertion details. + pub fn with_stdout_data(&mut self, expected: impl snapbox::IntoData) -> &mut Self { + self.expect_stdout_data = Some(expected.into_data()); + self + } + + /// Verifies that stderr is equal to the given lines. + /// + /// See [`compare::assert_e2e`] for assertion details. + pub fn with_stderr_data(&mut self, expected: impl snapbox::IntoData) -> &mut Self { + self.expect_stderr_data = Some(expected.into_data()); + self + } + /// Writes the given lines to stdin. pub fn with_stdin(&mut self, expected: S) -> &mut Self { self.expect_stdin = Some(expected.to_string()); @@ -593,6 +615,7 @@ impl Execs { /// its output. /// /// See [`compare`] for supported patterns. + #[deprecated(note = "replaced with `Execs::with_stdout_data(expected)`")] pub fn with_stdout_contains(&mut self, expected: S) -> &mut Self { self.expect_stdout_contains.push(expected.to_string()); self @@ -602,6 +625,7 @@ impl Execs { /// its output. /// /// See [`compare`] for supported patterns. + #[deprecated(note = "replaced with `Execs::with_stderr_data(expected)`")] pub fn with_stderr_contains(&mut self, expected: S) -> &mut Self { self.expect_stderr_contains.push(expected.to_string()); self @@ -611,6 +635,7 @@ impl Execs { /// its output, and should be repeated `number` times. /// /// See [`compare`] for supported patterns. + #[deprecated(note = "replaced with `Execs::with_stdout_data(expected)`")] pub fn with_stdout_contains_n(&mut self, expected: S, number: usize) -> &mut Self { self.expect_stdout_contains_n .push((expected.to_string(), number)); @@ -622,6 +647,7 @@ impl Execs { /// See [`compare`] for supported patterns. /// /// See note on [`Self::with_stderr_does_not_contain`]. + #[deprecated] pub fn with_stdout_does_not_contain(&mut self, expected: S) -> &mut Self { self.expect_stdout_not_contains.push(expected.to_string()); self @@ -636,6 +662,7 @@ impl Execs { /// your test will pass without verifying the correct behavior. If /// possible, write the test first so that it fails, and then implement /// your fix/feature to make it pass. + #[deprecated] pub fn with_stderr_does_not_contain(&mut self, expected: S) -> &mut Self { self.expect_stderr_not_contains.push(expected.to_string()); self @@ -645,6 +672,7 @@ impl Execs { /// ignoring the order of the lines. /// /// See [`Execs::with_stderr_unordered`] for more details. + #[deprecated(note = "replaced with `Execs::with_stdout_data(expected.unordered())`")] pub fn with_stdout_unordered(&mut self, expected: S) -> &mut Self { self.expect_stdout_unordered.push(expected.to_string()); self @@ -671,6 +699,7 @@ impl Execs { /// /// This will randomly fail if the other crate name is `bar`, and the /// order changes. + #[deprecated(note = "replaced with `Execs::with_stderr_data(expected.unordered())`")] pub fn with_stderr_unordered(&mut self, expected: S) -> &mut Self { self.expect_stderr_unordered.push(expected.to_string()); self @@ -698,6 +727,7 @@ impl Execs { /// /// Be careful writing the `without` fragments, see note in /// `with_stderr_does_not_contain`. + #[deprecated] pub fn with_stderr_line_without( &mut self, with: &[S], @@ -730,6 +760,7 @@ impl Execs { /// - The order of arrays is ignored. /// - Strings support patterns described in [`compare`]. /// - Use `"{...}"` to match any object. + #[deprecated(note = "replaced with `Execs::with_stdout_data(expected.json_lines())`")] pub fn with_json(&mut self, expected: &str) -> &mut Self { self.expect_json = Some(expected.to_string()); self @@ -744,6 +775,7 @@ impl Execs { /// what you are doing. /// /// See `with_json` for more detail. + #[deprecated] pub fn with_json_contains_unordered(&mut self, expected: &str) -> &mut Self { match &mut self.expect_json_contains_unordered { None => self.expect_json_contains_unordered = Some(expected.to_string()), @@ -845,6 +877,17 @@ impl Execs { self } + pub fn overlay_registry(&mut self, url: &Url, path: &str) -> &mut Self { + if let Some(ref mut p) = self.process_builder { + let env_value = format!("{}={}", url, path); + p.env( + "__CARGO_TEST_DEPENDENCY_CONFUSION_VULNERABILITY_DO_NOT_USE_THIS", + env_value, + ); + } + self + } + pub fn enable_split_debuginfo_packed(&mut self) -> &mut Self { self.env("CARGO_PROFILE_DEV_SPLIT_DEBUGINFO", "packed") .env("CARGO_PROFILE_TEST_SPLIT_DEBUGINFO", "packed") @@ -908,11 +951,14 @@ impl Execs { } } + #[track_caller] fn verify_checks_output(&self, stdout: &[u8], stderr: &[u8]) { if self.expect_exit_code.unwrap_or(0) != 0 && self.expect_stdout.is_none() && self.expect_stdin.is_none() && self.expect_stderr.is_none() + && self.expect_stdout_data.is_none() + && self.expect_stderr_data.is_none() && self.expect_stdout_contains.is_empty() && self.expect_stderr_contains.is_empty() && self.expect_stdout_contains_n.is_empty() @@ -934,6 +980,7 @@ impl Execs { } } + #[track_caller] fn match_process(&self, process: &ProcessBuilder) -> Result { println!("running {}", process); let res = if self.stream_output { @@ -984,6 +1031,7 @@ impl Execs { } } + #[track_caller] fn match_output(&self, code: Option, stdout: &[u8], stderr: &[u8]) -> Result<()> { self.verify_checks_output(stdout, stderr); let stdout = std::str::from_utf8(stdout).expect("stdout is not utf8"); @@ -1008,6 +1056,24 @@ impl Execs { if let Some(expect_stderr) = &self.expect_stderr { compare::match_exact(expect_stderr, stderr, "stderr", stdout, cwd)?; } + if let Some(expect_stdout_data) = &self.expect_stdout_data { + if let Err(err) = self.assert.try_eq( + Some(&"stdout"), + stdout.into_data(), + expect_stdout_data.clone(), + ) { + panic!("{err}") + } + } + if let Some(expect_stderr_data) = &self.expect_stderr_data { + if let Err(err) = self.assert.try_eq( + Some(&"stderr"), + stderr.into_data(), + expect_stderr_data.clone(), + ) { + panic!("{err}") + } + } for expect in self.expect_stdout_contains.iter() { compare::match_contains(expect, stdout, cwd)?; } @@ -1060,6 +1126,8 @@ pub fn execs() -> Execs { expect_stderr: None, expect_stdin: None, expect_exit_code: Some(0), + expect_stdout_data: None, + expect_stderr_data: None, expect_stdout_contains: Vec::new(), expect_stderr_contains: Vec::new(), expect_stdout_contains_n: Vec::new(), @@ -1071,6 +1139,7 @@ pub fn execs() -> Execs { expect_json: None, expect_json_contains_unordered: None, stream_output: false, + assert: compare::assert_e2e(), } } diff --git a/crates/cargo-test-support/src/registry.rs b/crates/cargo-test-support/src/registry.rs index f8b4b1447822..6ddd59e38a8c 100644 --- a/crates/cargo-test-support/src/registry.rs +++ b/crates/cargo-test-support/src/registry.rs @@ -1649,7 +1649,12 @@ impl Package { /// Returns the path to the compressed package file. pub fn archive_dst(&self) -> PathBuf { if self.local { - registry_path().join(format!("{}-{}.crate", self.name, self.vers)) + let path = if self.alternative { + alt_registry_path() + } else { + registry_path() + }; + path.join(format!("{}-{}.crate", self.name, self.vers)) } else if self.alternative { alt_dl_path() .join(&self.name) diff --git a/crates/cargo-util-schemas/Cargo.toml b/crates/cargo-util-schemas/Cargo.toml index 848e235a759c..fbf7ae87ea8d 100644 --- a/crates/cargo-util-schemas/Cargo.toml +++ b/crates/cargo-util-schemas/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cargo-util-schemas" -version = "0.4.0" +version = "0.5.0" rust-version = "1.78" # MSRV:1 edition.workspace = true license.workspace = true diff --git a/crates/cargo-util-schemas/src/manifest/mod.rs b/crates/cargo-util-schemas/src/manifest/mod.rs index 25df09ba6f76..7ca2de5564dd 100644 --- a/crates/cargo-util-schemas/src/manifest/mod.rs +++ b/crates/cargo-util-schemas/src/manifest/mod.rs @@ -1223,7 +1223,6 @@ pub struct TomlTarget { pub doctest: Option, pub bench: Option, pub doc: Option, - pub plugin: Option, pub doc_scrape_examples: Option, pub proc_macro: Option, #[serde(rename = "proc_macro")] diff --git a/crates/mdman/src/format/man.rs b/crates/mdman/src/format/man.rs index edb5c05e34bb..72d45d352774 100644 --- a/crates/mdman/src/format/man.rs +++ b/crates/mdman/src/format/man.rs @@ -140,7 +140,7 @@ impl<'e> ManRenderer<'e> { suppress_paragraph = true; } } - Tag::BlockQuote => { + Tag::BlockQuote(_kind) => { self.flush(); // .RS = move left margin over 3 // .ll = shrink line length @@ -356,6 +356,8 @@ impl<'e> ManRenderer<'e> { } Event::TaskListMarker(_b) => unimplemented!(), Event::InlineHtml(..) => unimplemented!(), + Event::InlineMath(..) => unimplemented!(), + Event::DisplayMath(..) => unimplemented!(), } } Ok(()) diff --git a/crates/mdman/src/format/text.rs b/crates/mdman/src/format/text.rs index 5a858fcc792e..30e01d6faa98 100644 --- a/crates/mdman/src/format/text.rs +++ b/crates/mdman/src/format/text.rs @@ -137,7 +137,7 @@ impl<'e> TextRenderer<'e> { self.indent = (level as usize - 1) * 3 + 1; } } - Tag::BlockQuote => { + Tag::BlockQuote(_kind) => { self.indent += 3; } Tag::CodeBlock(_kind) => { @@ -347,6 +347,8 @@ impl<'e> TextRenderer<'e> { } Event::TaskListMarker(_b) => unimplemented!(), Event::InlineHtml(..) => unimplemented!(), + Event::InlineMath(..) => unimplemented!(), + Event::DisplayMath(..) => unimplemented!(), } } Ok(()) diff --git a/crates/xtask-bump-check/src/xtask.rs b/crates/xtask-bump-check/src/xtask.rs index 07148e554f58..e602d5df3a7d 100644 --- a/crates/xtask-bump-check/src/xtask.rs +++ b/crates/xtask-bump-check/src/xtask.rs @@ -16,7 +16,6 @@ use std::fs; use std::task; use cargo::core::dependency::Dependency; -use cargo::core::registry::PackageRegistry; use cargo::core::Package; use cargo::core::Registry; use cargo::core::SourceId; @@ -137,7 +136,7 @@ fn bump_check(args: &clap::ArgMatches, gctx: &cargo::util::GlobalContext) -> Car let mut needs_bump = Vec::new(); - check_crates_io(gctx, &changed_members, &mut needs_bump)?; + check_crates_io(&ws, &changed_members, &mut needs_bump)?; if let Some(referenced_commit) = referenced_commit.as_ref() { status(&format!("compare against `{}`", referenced_commit.id()))?; @@ -385,12 +384,13 @@ fn symmetric_diff<'a>( /// /// Assumption: We always release a version larger than all existing versions. fn check_crates_io<'a>( - gctx: &GlobalContext, + ws: &Workspace<'a>, changed_members: &HashMap<&'a str, &'a Package>, needs_bump: &mut Vec<&'a Package>, ) -> CargoResult<()> { + let gctx = ws.gctx(); let source_id = SourceId::crates_io(gctx)?; - let mut registry = PackageRegistry::new(gctx)?; + let mut registry = ws.package_registry()?; let _lock = gctx.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?; registry.lock_patches(); gctx.shell().status( diff --git a/crates/xtask-lint-docs/Cargo.toml b/crates/xtask-lint-docs/Cargo.toml new file mode 100644 index 000000000000..16f15d2efe70 --- /dev/null +++ b/crates/xtask-lint-docs/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "xtask-lint-docs" +version = "0.1.0" +edition.workspace = true +publish = false + +[dependencies] +anyhow.workspace = true +cargo.workspace = true +clap.workspace = true +itertools.workspace = true + +[lints] +workspace = true diff --git a/crates/xtask-lint-docs/src/main.rs b/crates/xtask-lint-docs/src/main.rs new file mode 100644 index 000000000000..79862d6c4002 --- /dev/null +++ b/crates/xtask-lint-docs/src/main.rs @@ -0,0 +1,108 @@ +use cargo::util::command_prelude::{flag, ArgMatchesExt}; +use cargo::util::lints::{Lint, LintLevel}; +use itertools::Itertools; +use std::fmt::Write; +use std::path::PathBuf; + +fn cli() -> clap::Command { + clap::Command::new("xtask-lint-docs").arg(flag("check", "Check that the docs are up-to-date")) +} + +fn main() -> anyhow::Result<()> { + let args = cli().get_matches(); + let check = args.flag("check"); + + let mut allow = Vec::new(); + let mut warn = Vec::new(); + let mut deny = Vec::new(); + let mut forbid = Vec::new(); + + let mut lint_docs = String::new(); + for lint in cargo::util::lints::LINTS + .iter() + .sorted_by_key(|lint| lint.name) + { + if lint.docs.is_some() { + let sectipn = match lint.default_level { + LintLevel::Allow => &mut allow, + LintLevel::Warn => &mut warn, + LintLevel::Deny => &mut deny, + LintLevel::Forbid => &mut forbid, + }; + sectipn.push(lint.name); + add_lint(lint, &mut lint_docs)?; + } + } + + let mut buf = String::new(); + writeln!(buf, "# Lints\n")?; + writeln!( + buf, + "Note: [Cargo's linting system is unstable](unstable.md#lintscargo) and can only be used on nightly toolchains" + )?; + writeln!(buf)?; + + if !allow.is_empty() { + add_level_section(LintLevel::Allow, &allow, &mut buf)?; + } + if !warn.is_empty() { + add_level_section(LintLevel::Warn, &warn, &mut buf)?; + } + if !deny.is_empty() { + add_level_section(LintLevel::Deny, &deny, &mut buf)?; + } + if !forbid.is_empty() { + add_level_section(LintLevel::Forbid, &forbid, &mut buf)?; + } + + buf.push_str(&lint_docs); + + if check { + let old = std::fs::read_to_string(lint_docs_path())?; + if old != buf { + anyhow::bail!( + "The lints documentation is out-of-date. Run `cargo lint-docs` to update it." + ); + } + } else { + std::fs::write(lint_docs_path(), buf)?; + } + Ok(()) +} + +fn add_lint(lint: &Lint, buf: &mut String) -> std::fmt::Result { + writeln!(buf, "## `{}`", lint.name)?; + writeln!(buf, "Set to `{}` by default", lint.default_level)?; + writeln!(buf, "{}\n", lint.docs.as_ref().unwrap()) +} + +fn add_level_section(level: LintLevel, lint_names: &[&str], buf: &mut String) -> std::fmt::Result { + let title = match level { + LintLevel::Allow => "Allowed-by-default", + LintLevel::Warn => "Warn-by-default", + LintLevel::Deny => "Deny-by-default", + LintLevel::Forbid => "Forbid-by-default", + }; + writeln!(buf, "## {title}\n")?; + writeln!( + buf, + "These lints are all set to the '{}' level by default.", + level + )?; + + for name in lint_names { + writeln!(buf, "- [`{}`](#{})", name, name)?; + } + writeln!(buf)?; + Ok(()) +} + +fn lint_docs_path() -> PathBuf { + let pkg_root = env!("CARGO_MANIFEST_DIR"); + let ws_root = PathBuf::from(format!("{pkg_root}/../..")); + let path = { + let path = ws_root.join("src/doc/src/reference/lints.md"); + path.canonicalize().unwrap_or(path) + }; + path +} diff --git a/src/bin/cargo/commands/add.rs b/src/bin/cargo/commands/add.rs index 9c67eb8343cb..30956b00479f 100644 --- a/src/bin/cargo/commands/add.rs +++ b/src/bin/cargo/commands/add.rs @@ -214,11 +214,9 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { }; add(&ws, &options)?; - if !dry_run { - // Reload the workspace since we've changed dependencies - let ws = args.workspace(gctx)?; - resolve_ws(&ws)?; - } + // Reload the workspace since we've changed dependencies + let ws = args.workspace(gctx)?; + resolve_ws(&ws, dry_run)?; Ok(()) } diff --git a/src/bin/cargo/commands/bench.rs b/src/bin/cargo/commands/bench.rs index f6d8766570d6..c79d7cb350d0 100644 --- a/src/bin/cargo/commands/bench.rs +++ b/src/bin/cargo/commands/bench.rs @@ -63,7 +63,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { args.compile_options(gctx, CompileMode::Bench, Some(&ws), ProfileChecking::Custom)?; compile_opts.build_config.requested_profile = - args.get_profile_name(gctx, "bench", ProfileChecking::Custom)?; + args.get_profile_name("bench", ProfileChecking::Custom)?; let ops = TestOptions { no_run: args.flag("no-run"), diff --git a/src/bin/cargo/commands/build.rs b/src/bin/cargo/commands/build.rs index 308ce2ce6a71..26f7af316097 100644 --- a/src/bin/cargo/commands/build.rs +++ b/src/bin/cargo/commands/build.rs @@ -34,7 +34,7 @@ pub fn cli() -> Command { .arg_parallel() .arg_target_triple("Build for the target triple") .arg_target_dir() - .arg_out_dir() + .arg_artifact_dir() .arg_build_plan() .arg_unit_graph() .arg_timings() @@ -50,15 +50,32 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { let mut compile_opts = args.compile_options(gctx, CompileMode::Build, Some(&ws), ProfileChecking::Custom)?; - if let Some(out_dir) = args.value_of_path("out-dir", gctx) { - compile_opts.build_config.export_dir = Some(out_dir); - } else if let Some(out_dir) = gctx.build_config()?.out_dir.as_ref() { - let out_dir = out_dir.resolve_path(gctx); - compile_opts.build_config.export_dir = Some(out_dir); + if let Some(artifact_dir) = args.value_of_path("artifact-dir", gctx) { + // If the user specifies `--artifact-dir`, use that + compile_opts.build_config.export_dir = Some(artifact_dir); + } else if let Some(artifact_dir) = args.value_of_path("out-dir", gctx) { + // `--out-dir` is deprecated, but still supported for now + gctx.shell() + .warn("the --out-dir flag has been changed to --artifact-dir")?; + compile_opts.build_config.export_dir = Some(artifact_dir); + } else if let Some(artifact_dir) = gctx.build_config()?.artifact_dir.as_ref() { + // If a CLI option is not specified for choosing the artifact dir, use the `artifact-dir` from the build config, if + // present + let artifact_dir = artifact_dir.resolve_path(gctx); + compile_opts.build_config.export_dir = Some(artifact_dir); + } else if let Some(artifact_dir) = gctx.build_config()?.out_dir.as_ref() { + // As a last priority, check `out-dir` in the build config + gctx.shell() + .warn("the out-dir config option has been changed to artifact-dir")?; + let artifact_dir = artifact_dir.resolve_path(gctx); + compile_opts.build_config.export_dir = Some(artifact_dir); } + if compile_opts.build_config.export_dir.is_some() { - gctx.cli_unstable().fail_if_stable_opt("--out-dir", 6790)?; + gctx.cli_unstable() + .fail_if_stable_opt("--artifact-dir", 6790)?; } + ops::compile(&ws, &compile_opts)?; Ok(()) } diff --git a/src/bin/cargo/commands/clean.rs b/src/bin/cargo/commands/clean.rs index e358b9671509..1764c0bca1c9 100644 --- a/src/bin/cargo/commands/clean.rs +++ b/src/bin/cargo/commands/clean.rs @@ -146,7 +146,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { gctx, spec: values(args, "package"), targets: args.targets()?, - requested_profile: args.get_profile_name(gctx, "dev", ProfileChecking::Custom)?, + requested_profile: args.get_profile_name("dev", ProfileChecking::Custom)?, profile_specified: args.contains_id("profile") || args.flag("release"), doc: args.flag("doc"), dry_run: args.dry_run(), diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs index e188d6a0d677..8aaaeb87b0e4 100644 --- a/src/bin/cargo/commands/install.rs +++ b/src/bin/cargo/commands/install.rs @@ -85,10 +85,13 @@ pub fn cli() -> Command { ) .arg_features() .arg_parallel() - .arg(flag( - "debug", - "Build in debug mode (with the 'dev' profile) instead of release mode", - )) + .arg( + flag( + "debug", + "Build in debug mode (with the 'dev' profile) instead of release mode", + ) + .conflicts_with("profile"), + ) .arg_redundant_default_mode("release", "install", "debug") .arg_profile("Install artifacts with the specified profile") .arg_target_triple("Build for the target triple") @@ -196,7 +199,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { )?; compile_opts.build_config.requested_profile = - args.get_profile_name(gctx, "release", ProfileChecking::Custom)?; + args.get_profile_name("release", ProfileChecking::Custom)?; if args.flag("list") { ops::install_list(root, gctx)?; diff --git a/src/bin/cargo/commands/remove.rs b/src/bin/cargo/commands/remove.rs index 25179487c934..b5695e59937f 100644 --- a/src/bin/cargo/commands/remove.rs +++ b/src/bin/cargo/commands/remove.rs @@ -121,7 +121,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { ws.gctx() .shell() .set_verbosity(cargo::core::Verbosity::Quiet); - let resolve = resolve_ws(&ws); + let resolve = resolve_ws(&ws, dry_run); ws.gctx().shell().set_verbosity(verbosity); resolve?.1 }; @@ -129,7 +129,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { // Attempt to gc unused patches and re-resolve if anything is removed if gc_unused_patches(&workspace, &resolve)? { let ws = args.workspace(gctx)?; - resolve_ws(&ws)?; + resolve_ws(&ws, dry_run)?; } } Ok(()) diff --git a/src/bin/cargo/commands/test.rs b/src/bin/cargo/commands/test.rs index 1815ee62f9f7..c2657a78f054 100644 --- a/src/bin/cargo/commands/test.rs +++ b/src/bin/cargo/commands/test.rs @@ -74,7 +74,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { args.compile_options(gctx, CompileMode::Test, Some(&ws), ProfileChecking::Custom)?; compile_opts.build_config.requested_profile = - args.get_profile_name(gctx, "test", ProfileChecking::Custom)?; + args.get_profile_name("test", ProfileChecking::Custom)?; // `TESTNAME` is actually an argument of the test binary, but it's // important, so we explicitly mention it and reconfigure. diff --git a/src/bin/cargo/commands/update.rs b/src/bin/cargo/commands/update.rs index fb394e4aa336..492be07c783a 100644 --- a/src/bin/cargo/commands/update.rs +++ b/src/bin/cargo/commands/update.rs @@ -35,6 +35,13 @@ pub fn cli() -> Command { .value_name("PRECISE") .requires("package-group"), ) + .arg( + flag( + "breaking", + "Update [SPEC] to latest SemVer-breaking version (unstable)", + ) + .short('b'), + ) .arg_silent_suggestion() .arg( flag("workspace", "Only update the workspace packages") @@ -59,7 +66,8 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { gctx.cli_unstable().msrv_policy, )?; } - let ws = args.workspace(gctx)?; + + let mut ws = args.workspace(gctx)?; if args.is_present_with_zero_values("package") { print_available_packages(&ws)?; @@ -89,6 +97,24 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { workspace: args.flag("workspace"), gctx, }; - ops::update_lockfile(&ws, &update_opts)?; + + if args.flag("breaking") { + gctx.cli_unstable() + .fail_if_stable_opt("--breaking", 12425)?; + + let upgrades = ops::upgrade_manifests(&mut ws, &update_opts.to_update)?; + ops::resolve_ws(&ws, update_opts.dry_run)?; + ops::write_manifest_upgrades(&ws, &upgrades, update_opts.dry_run)?; + + if update_opts.dry_run { + update_opts + .gctx + .shell() + .warn("aborting update due to dry run")?; + } + } else { + ops::update_lockfile(&ws, &update_opts)?; + } + Ok(()) } diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index 9536e58be566..0f66d6dbbc66 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -36,11 +36,11 @@ pub struct BuildConfig { /// A thread used by `cargo fix` to receive messages on a socket regarding /// the success/failure of applying fixes. pub rustfix_diagnostic_server: Rc>>, - /// 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. - // Note that, although the cmd-line flag name is `out-dir`, in code we use - // `export_dir`, to avoid confusion with out dir at `target/debug/deps`. + /// The directory to copy final artifacts to. Note that even if + /// `artifact-dir` is set, a copy of artifacts still can be found at + /// `target/(debug\release)` as usual. + /// Named `export_dir` to avoid confusion with + /// `CompilationFiles::artifact_dir`. pub export_dir: Option, /// `true` to output a future incompatibility report at the end of the build pub future_incompat_report: bool, diff --git a/src/cargo/core/compiler/build_runner/compilation_files.rs b/src/cargo/core/compiler/build_runner/compilation_files.rs index 27c555a26941..41ef89d6f0b6 100644 --- a/src/cargo/core/compiler/build_runner/compilation_files.rs +++ b/src/cargo/core/compiler/build_runner/compilation_files.rs @@ -121,7 +121,7 @@ pub struct OutputFile { /// If it should be linked into `target`, and what it should be called /// (e.g., without metadata). pub hardlink: Option, - /// If `--out-dir` is specified, the absolute path to the exported file. + /// If `--artifact-dir` is specified, the absolute path to the exported file. pub export_path: Option, /// Type of the file (library / debug symbol / else). pub flavor: FileFlavor, @@ -213,7 +213,7 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { } } - /// Additional export directory from `--out-dir`. + /// Additional export directory from `--artifact-dir`. pub fn export_dir(&self) -> Option { self.export_dir.clone() } diff --git a/src/cargo/core/compiler/build_runner/mod.rs b/src/cargo/core/compiler/build_runner/mod.rs index c5a926d50afa..ed4d6fcdc354 100644 --- a/src/cargo/core/compiler/build_runner/mod.rs +++ b/src/cargo/core/compiler/build_runner/mod.rs @@ -574,7 +574,7 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> { if let Some(ref export_path) = output.export_path { if let Some(other_unit) = output_collisions.insert(export_path.clone(), unit) { self.bcx.gctx.shell().warn(format!( - "`--out-dir` filename collision.\n\ + "`--artifact-dir` filename collision.\n\ {}\ The exported filenames should be unique.\n\ {}", diff --git a/src/cargo/core/compiler/standard_lib.rs b/src/cargo/core/compiler/standard_lib.rs index 684e4426c04a..3e387bdddccf 100644 --- a/src/cargo/core/compiler/standard_lib.rs +++ b/src/cargo/core/compiler/standard_lib.rs @@ -149,6 +149,7 @@ pub fn resolve_std<'gctx>( let cli_features = CliFeatures::from_command_line( &features, /*all_features*/ false, /*uses_default_features*/ false, )?; + let dry_run = false; let resolve = ops::resolve_ws_with_opts( &std_ws, target_data, @@ -157,6 +158,7 @@ pub fn resolve_std<'gctx>( &specs, HasDevUnits::No, crate::core::resolver::features::ForceAllTargets::No, + dry_run, )?; Ok(( resolve.pkg_set, diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 14245c410e82..a45a26a765ff 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -905,7 +905,7 @@ impl Target { pub fn documented(&self) -> bool { self.inner.doc } - // A plugin, proc-macro, or build-script. + // A proc-macro or build-script. pub fn for_host(&self) -> bool { self.inner.for_host } diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index 192369c48842..bcbd819905a2 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -194,8 +194,10 @@ pub struct LockedPatchDependency { } impl<'gctx> PackageRegistry<'gctx> { - pub fn new(gctx: &'gctx GlobalContext) -> CargoResult> { - let source_config = SourceConfigMap::new(gctx)?; + pub fn new_with_source_config( + gctx: &'gctx GlobalContext, + source_config: SourceConfigMap<'gctx>, + ) -> CargoResult> { Ok(PackageRegistry { gctx, sources: SourceMap::new(), diff --git a/src/cargo/core/resolver/features.rs b/src/cargo/core/resolver/features.rs index fdb49c0bf9f5..807bdc4533a8 100644 --- a/src/cargo/core/resolver/features.rs +++ b/src/cargo/core/resolver/features.rs @@ -426,10 +426,12 @@ pub struct FeatureResolver<'a, 'gctx> { /// If this is `true`, then a non-default `feature_key` needs to be tracked while /// traversing the graph. /// - /// This is only here to avoid calling `is_proc_macro` when all feature - /// options are disabled (because `is_proc_macro` can trigger downloads). - /// This has to be separate from `FeatureOpts.decouple_host_deps` because + /// This is only here to avoid calling [`has_any_proc_macro`] when all feature + /// options are disabled (because [`has_any_proc_macro`] can trigger downloads). + /// This has to be separate from [`FeatureOpts::decouple_host_deps`] because /// `for_host` tracking is also needed for `itarget` to work properly. + /// + /// [`has_any_proc_macro`]: FeatureResolver::has_any_proc_macro track_for_host: bool, /// `dep_name?/feat_name` features that will be activated if `dep_name` is /// ever activated. @@ -490,7 +492,7 @@ impl<'a, 'gctx> FeatureResolver<'a, 'gctx> { let member_features = self.ws.members_with_features(specs, cli_features)?; for (member, cli_features) in &member_features { let fvs = self.fvs_from_requested(member.package_id(), cli_features); - let fk = if self.track_for_host && self.is_proc_macro(member.package_id()) { + let fk = if self.track_for_host && self.has_any_proc_macro(member.package_id()) { // Also activate for normal dependencies. This is needed if the // proc-macro includes other targets (like binaries or tests), // or running in `cargo test`. Note that in a workspace, if @@ -852,7 +854,7 @@ impl<'a, 'gctx> FeatureResolver<'a, 'gctx> { // for various targets which are either specified in the manifest // or on the cargo command-line. let lib_fk = if fk == FeaturesFor::default() { - (self.track_for_host && (dep.is_build() || self.is_proc_macro(dep_id))) + (self.track_for_host && (dep.is_build() || self.has_proc_macro_lib(dep_id))) .then(|| FeaturesFor::HostDep) .unwrap_or_default() } else { @@ -957,10 +959,24 @@ impl<'a, 'gctx> FeatureResolver<'a, 'gctx> { } } - fn is_proc_macro(&self, package_id: PackageId) -> bool { + /// Whether the given package has any proc macro target, including proc-macro examples. + fn has_any_proc_macro(&self, package_id: PackageId) -> bool { self.package_set .get_one(package_id) .expect("packages downloaded") .proc_macro() } + + /// Whether the given package is a proc macro lib target. + /// + /// This is useful for checking if a dependency is a proc macro, + /// as it is not possible to depend on a non-lib target as a proc-macro. + fn has_proc_macro_lib(&self, package_id: PackageId) -> bool { + self.package_set + .get_one(package_id) + .expect("packages downloaded") + .library() + .map(|lib| lib.proc_macro()) + .unwrap_or_default() + } } diff --git a/src/cargo/core/summary.rs b/src/cargo/core/summary.rs index ec0197cf40d0..d7744e24ef73 100644 --- a/src/cargo/core/summary.rs +++ b/src/cargo/core/summary.rs @@ -103,15 +103,25 @@ impl Summary { Rc::make_mut(&mut self.inner).checksum = Some(cksum); } - pub fn map_dependencies(mut self, f: F) -> Summary + pub fn map_dependencies(self, mut f: F) -> Summary where F: FnMut(Dependency) -> Dependency, + { + self.try_map_dependencies(|dep| Ok(f(dep))).unwrap() + } + + pub fn try_map_dependencies(mut self, f: F) -> CargoResult + where + F: FnMut(Dependency) -> CargoResult, { { let slot = &mut Rc::make_mut(&mut self.inner).dependencies; - *slot = mem::take(slot).into_iter().map(f).collect(); + *slot = mem::take(slot) + .into_iter() + .map(f) + .collect::>()?; } - self + Ok(self) } pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Summary { diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index 1dc75c881e4a..d1999aafc2f8 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -20,7 +20,7 @@ use crate::core::{ }; use crate::core::{EitherManifest, Package, SourceId, VirtualManifest}; use crate::ops; -use crate::sources::{PathSource, CRATES_IO_INDEX, CRATES_IO_REGISTRY}; +use crate::sources::{PathSource, SourceConfigMap, CRATES_IO_INDEX, CRATES_IO_REGISTRY}; use crate::util::edit_distance; use crate::util::errors::{CargoResult, ManifestError}; use crate::util::interning::InternedString; @@ -109,6 +109,9 @@ pub struct Workspace<'gctx> { /// Workspace-level custom metadata custom_metadata: Option, + + /// Local overlay configuration. See [`crate::sources::overlay`]. + local_overlays: HashMap, } // Separate structure for tracking loaded packages (to avoid loading anything @@ -237,6 +240,7 @@ impl<'gctx> Workspace<'gctx> { resolve_behavior: ResolveBehavior::V1, resolve_honors_rust_version: false, custom_metadata: None, + local_overlays: HashMap::new(), } } @@ -1674,6 +1678,44 @@ impl<'gctx> Workspace<'gctx> { // Cargo to panic, see issue #10545. self.is_member(&unit.pkg) && !(unit.target.for_host() || unit.pkg.proc_macro()) } + + /// Adds a local package registry overlaying a `SourceId`. + /// + /// See [`crate::sources::overlay::DependencyConfusionThreatOverlaySource`] for why you shouldn't use this. + pub fn add_local_overlay(&mut self, id: SourceId, registry_path: PathBuf) { + self.local_overlays.insert(id, registry_path); + } + + /// Builds a package registry that reflects this workspace configuration. + pub fn package_registry(&self) -> CargoResult> { + let source_config = + SourceConfigMap::new_with_overlays(self.gctx(), self.local_overlays()?)?; + PackageRegistry::new_with_source_config(self.gctx(), source_config) + } + + /// Returns all the configured local overlays, including the ones from our secret environment variable. + fn local_overlays(&self) -> CargoResult> { + let mut ret = self + .local_overlays + .iter() + .map(|(id, path)| Ok((*id, SourceId::for_local_registry(path)?))) + .collect::>>()?; + + if let Ok(overlay) = self + .gctx + .get_env("__CARGO_TEST_DEPENDENCY_CONFUSION_VULNERABILITY_DO_NOT_USE_THIS") + { + let (url, path) = overlay.split_once('=').ok_or(anyhow::anyhow!( + "invalid overlay format. I won't tell you why; you shouldn't be using it anyway" + ))?; + ret.push(( + SourceId::from_url(url)?, + SourceId::for_local_registry(path.as_ref())?, + )); + } + + Ok(ret.into_iter()) + } } impl<'gctx> Packages<'gctx> { diff --git a/src/cargo/ops/cargo_add/mod.rs b/src/cargo/ops/cargo_add/mod.rs index 1781d4c93598..a8fa97afe07a 100644 --- a/src/cargo/ops/cargo_add/mod.rs +++ b/src/cargo/ops/cargo_add/mod.rs @@ -78,7 +78,7 @@ pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<( ); } - let mut registry = PackageRegistry::new(options.gctx)?; + let mut registry = workspace.package_registry()?; let deps = { let _lock = options diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index 5969bf287eb9..5297430b175a 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -77,7 +77,14 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> { if opts.spec.is_empty() { clean_ctx.remove_paths(&[target_dir.into_path_unlocked()])?; } else { - clean_specs(&mut clean_ctx, &ws, &profiles, &opts.targets, &opts.spec)?; + clean_specs( + &mut clean_ctx, + &ws, + &profiles, + &opts.targets, + &opts.spec, + opts.dry_run, + )?; } } @@ -91,11 +98,12 @@ fn clean_specs( profiles: &Profiles, targets: &[String], spec: &[String], + dry_run: bool, ) -> CargoResult<()> { // Clean specific packages. let requested_kinds = CompileKind::from_requested_targets(clean_ctx.gctx, targets)?; let target_data = RustcTargetData::new(ws, &requested_kinds)?; - let (pkg_set, resolve) = ops::resolve_ws(ws)?; + let (pkg_set, resolve) = ops::resolve_ws(ws, dry_run)?; let prof_dir_name = profiles.get_dir_name(); let host_layout = Layout::new(ws, None, &prof_dir_name)?; // Convert requested kinds to a Vec of layouts. diff --git a/src/cargo/ops/cargo_compile/mod.rs b/src/cargo/ops/cargo_compile/mod.rs index 68f1df76ba6f..0553e5e2d5de 100644 --- a/src/cargo/ops/cargo_compile/mod.rs +++ b/src/cargo/ops/cargo_compile/mod.rs @@ -264,6 +264,7 @@ pub fn create_bcx<'a, 'gctx>( HasDevUnits::No } }; + let dry_run = false; let resolve = ops::resolve_ws_with_opts( ws, &mut target_data, @@ -272,6 +273,7 @@ pub fn create_bcx<'a, 'gctx>( &specs, has_dev_units, crate::core::resolver::features::ForceAllTargets::No, + dry_run, )?; let WorkspaceResolve { mut pkg_set, diff --git a/src/cargo/ops/cargo_fetch.rs b/src/cargo/ops/cargo_fetch.rs index 761f171f1f69..37b56438cd60 100644 --- a/src/cargo/ops/cargo_fetch.rs +++ b/src/cargo/ops/cargo_fetch.rs @@ -19,7 +19,8 @@ pub fn fetch<'a>( options: &FetchOptions<'a>, ) -> CargoResult<(Resolve, PackageSet<'a>)> { ws.emit_warnings()?; - let (mut packages, resolve) = ops::resolve_ws(ws)?; + let dry_run = false; + let (mut packages, resolve) = ops::resolve_ws(ws, dry_run)?; let jobs = Some(JobsConfig::Integer(1)); let keep_going = false; diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index a662e891f387..e4304d74829c 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -561,7 +561,8 @@ impl<'gctx> InstallablePackage<'gctx> { // It would be best if `source` could be passed in here to avoid a // duplicate "Updating", but since `source` is taken by value, then it // wouldn't be available for `compile_ws`. - let (pkg_set, resolve) = ops::resolve_ws(&self.ws)?; + let dry_run = false; + let (pkg_set, resolve) = ops::resolve_ws(&self.ws, dry_run)?; ops::check_yanked( self.ws.gctx(), &pkg_set, diff --git a/src/cargo/ops/cargo_output_metadata.rs b/src/cargo/ops/cargo_output_metadata.rs index 408be75faf38..1aadc05d77a3 100644 --- a/src/cargo/ops/cargo_output_metadata.rs +++ b/src/cargo/ops/cargo_output_metadata.rs @@ -142,6 +142,7 @@ fn build_resolve_graph( // Note that even with --filter-platform we end up downloading host dependencies as well, // as that is the behavior of download_accessible. + let dry_run = false; let ws_resolve = ops::resolve_ws_with_opts( ws, &mut target_data, @@ -150,6 +151,7 @@ fn build_resolve_graph( &specs, HasDevUnits::Yes, force_all, + dry_run, )?; let package_map: BTreeMap = ws_resolve diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index 533852551c20..c9fc22c79307 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -9,7 +9,7 @@ use std::task::Poll; use crate::core::compiler::{BuildConfig, CompileMode, DefaultExecutor, Executor}; use crate::core::manifest::Target; use crate::core::resolver::CliFeatures; -use crate::core::{registry::PackageRegistry, resolver::HasDevUnits}; +use crate::core::resolver::HasDevUnits; use crate::core::{Feature, PackageIdSpecQuery, Shell, Verbosity, Workspace}; use crate::core::{Package, PackageId, PackageSet, Resolve, SourceId}; use crate::sources::PathSource; @@ -190,7 +190,8 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult